@rizom/brain 0.2.0-alpha.168 → 0.2.0-alpha.169
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/brain.js +34 -34
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/site.js +4 -4
- package/dist/site.js.map +1 -1
- package/package.json +1 -1
package/dist/brain.js
CHANGED
|
@@ -430,7 +430,7 @@ ${X}`:"")}function GM0(A,Q,w,$){return async(B,X)=>{if($){let Y={toolName:A,args
|
|
|
430
430
|
hash text NOT NULL,
|
|
431
431
|
created_at numeric
|
|
432
432
|
)
|
|
433
|
-
`;await A.session.run(B);let Y=(await A.values(AA`SELECT id, hash, created_at FROM ${AA.identifier($)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,Z=[];for(let H of w)if(!Y||Number(Y[2])<H.folderMillis){for(let W of H.sql)Z.push(A.run(AA.raw(W)));Z.push(A.run(AA`INSERT INTO ${AA.identifier($)} ("hash", "created_at") VALUES(${H.hash}, ${H.folderMillis})`))}await A.session.migrate(Z)}var Gl=r(()=>{lOA();N9()});async function pOA(A,Q){let w=Q?.child("entity-migrate")??gQ.getInstance().child("entity-migrate"),{db:$,client:B,url:X}=G20(A);w.debug("Running entity database migrations...");try{await D20(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 eF($,{migrationsFolder:Z}),await q20(B),w.debug("Entity database migrations completed successfully")}catch(Y){throw w.error("Entity database migration failed:",Y),Y}finally{B.close()}}var iOA=r(()=>{Gl();lL0();Y7()});async function dOA(A,Q){let w=Q?.child("job-queue-migrate")??gQ.getInstance().child("job-queue-migrate"),{db:$,client:B,url:X}=Z20(A);w.debug("Running job queue migrations...");try{await f20(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 eF($,{migrationsFolder:Z}),w.debug("Job queue migrations completed successfully")}catch(Y){throw w.error("Job queue migration failed:",Y),Y}finally{B.close()}}var nOA=r(()=>{Gl();PL0();Y7()});async function rOA(A,Q){let w=Q?.child("conversation-migrate")??gQ.getInstance().child("conversation-migrate"),{db:$,client:B,url:X}=H20(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 eF($,{migrationsFolder:Z}),w.debug("Conversation database migrations completed successfully")}catch(Y){throw w.error("Conversation database migration failed:",Y),Y}finally{B.close()}}var oOA=r(()=>{Gl();hL0();Y7()});async function sOA(A,Q){let w=Q?.child("runtime-state-migrate")??gQ.getInstance().child("runtime-state-migrate"),{db:$,client:B,url:X}=yw0(A);w.debug("Running runtime state migrations...");try{await gw0(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 eF($,{migrationsFolder:Z}),w.debug("Runtime state migrations completed successfully")}catch(Y){throw w.error("Runtime state migration failed:",Y),Y}finally{B.close()}}var aOA=r(()=>{Gl();Y7();jM0()});import{mkdir as iM0}from"fs/promises";function pw0(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function iw0(A=process.env){return uF(pw0(A))}async function dw0(A=process.env){let Q=pw0(A);try{await iM0(Q.dataDir,{recursive:!0}),await iM0(Q.cacheDir,{recursive:!0}),await iM0(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 uF(Q)}var nw0=r(()=>{cw0()});class Dl{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>dw0(),migrateEntities:pOA,migrateJobQueue:dOA,migrateConversations:rOA,migrateRuntimeState:sOA}}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 dM0=r(()=>{iOA();nOA();oOA();aOA();nw0()});function za2(){return process.env[qa2]}function tOA(){return za2()!=="production"}var qa2="NODE_ENV";var rw0;var nM0=r(()=>{C0();rw0=f.object({theme:f.object({primaryColor:f.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:f.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var AxA;var eOA=r(()=>{AxA={name:"@brains/chat-repl",version:"0.2.0-alpha.168",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 Gw=h((Ja2,ow0)=>{(function(){function A(t,G0){Object.defineProperty($.prototype,t,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",G0[0],G0[1])}})}function Q(t){if(t===null||typeof t!=="object")return null;return t=j0&&t[j0]||t["@@iterator"],typeof t==="function"?t:null}function w(t,G0){t=(t=t.constructor)&&(t.displayName||t.name)||"ReactClass";var J0=t+"."+G0;P0[J0]||(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.",G0,t),P0[J0]=!0)}function $(t,G0,J0){this.props=t,this.context=G0,this.refs=n0,this.updater=J0||E0}function B(){}function X(t,G0,J0){this.props=t,this.context=G0,this.refs=n0,this.updater=J0||E0}function Y(){}function Z(t){return""+t}function H(t){try{Z(t);var G0=!1}catch(F0){G0=!0}if(G0){G0=console;var J0=G0.error,N0=typeof Symbol==="function"&&Symbol.toStringTag&&t[Symbol.toStringTag]||t.constructor.name||"Object";return J0.call(G0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",N0),Z(t)}}function W(t){if(t==null)return null;if(typeof t==="function")return t.$$typeof===HA?null:t.displayName||t.name||null;if(typeof t==="string")return t;switch(t){case D0:return"Fragment";case f0:return"Profiler";case T:return"StrictMode";case i0:return"Suspense";case k0:return"SuspenseList";case S0:return"Activity"}if(typeof t==="object")switch(typeof t.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),t.$$typeof){case a:return"Portal";case i:return t.displayName||"Context";case b0:return(t._context.displayName||"Context")+".Consumer";case u0:var G0=t.render;return t=t.displayName,t||(t=G0.displayName||G0.name||"",t=t!==""?"ForwardRef("+t+")":"ForwardRef"),t;case _0:return G0=t.displayName||null,G0!==null?G0:W(t.type)||"Memo";case v0:G0=t._payload,t=t._init;try{return W(t(G0))}catch(J0){}}return null}function K(t){if(t===D0)return"<>";if(typeof t==="object"&&t!==null&&t.$$typeof===v0)return"<...>";try{var G0=W(t);return G0?"<"+G0+">":"<...>"}catch(J0){return"<...>"}}function U(){var t=WA.A;return t===null?null:t.getOwner()}function G(){return Error("react-stack-top-frame")}function q(t){if(o0.call(t,"key")){var G0=Object.getOwnPropertyDescriptor(t,"key").get;if(G0&&G0.isReactWarning)return!1}return t.key!==void 0}function V(t,G0){function J0(){GA||(GA=!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)",G0))}J0.isReactWarning=!0,Object.defineProperty(t,"key",{get:J0,configurable:!0})}function J(){var t=W(this.type);return RA[t]||(RA[t]=!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.")),t=this.props.ref,t!==void 0?t:null}function F(t,G0,J0,N0,F0,r0){var l0=J0.ref;return t={$$typeof:s,type:t,key:G0,props:J0,_owner:N0},(l0!==void 0?l0:null)!==null?Object.defineProperty(t,"ref",{enumerable:!1,get:J}):Object.defineProperty(t,"ref",{enumerable:!1,value:null}),t._store={},Object.defineProperty(t._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(t,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(t,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:F0}),Object.defineProperty(t,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:r0}),Object.freeze&&(Object.freeze(t.props),Object.freeze(t)),t}function k(t,G0){return G0=F(t.type,G0,t.props,t._owner,t._debugStack,t._debugTask),t._store&&(G0._store.validated=t._store.validated),G0}function j(t){_(t)?t._store&&(t._store.validated=1):typeof t==="object"&&t!==null&&t.$$typeof===v0&&(t._payload.status==="fulfilled"?_(t._payload.value)&&t._payload.value._store&&(t._payload.value._store.validated=1):t._store&&(t._store.validated=1))}function _(t){return typeof t==="object"&&t!==null&&t.$$typeof===s}function O(t){var G0={"=":"=0",":":"=2"};return"$"+t.replace(/[=:]/g,function(J0){return G0[J0]})}function R(t,G0){return typeof t==="object"&&t!==null&&t.key!=null?(H(t.key),O(""+t.key)):G0.toString(36)}function x(t){switch(t.status){case"fulfilled":return t.value;case"rejected":throw t.reason;default:switch(typeof t.status==="string"?t.then(Y,Y):(t.status="pending",t.then(function(G0){t.status==="pending"&&(t.status="fulfilled",t.value=G0)},function(G0){t.status==="pending"&&(t.status="rejected",t.reason=G0)})),t.status){case"fulfilled":return t.value;case"rejected":throw t.reason}}throw t}function M(t,G0,J0,N0,F0){var r0=typeof t;if(r0==="undefined"||r0==="boolean")t=null;var l0=!1;if(t===null)l0=!0;else switch(r0){case"bigint":case"string":case"number":l0=!0;break;case"object":switch(t.$$typeof){case s:case a:l0=!0;break;case v0:return l0=t._init,M(l0(t._payload),G0,J0,N0,F0)}}if(l0){l0=t,F0=F0(l0);var BA=N0===""?"."+R(l0,0):N0;return JA(F0)?(J0="",BA!=null&&(J0=BA.replace(x0,"$&/")+"/"),M(F0,G0,J0,"",function(hA){return hA})):F0!=null&&(_(F0)&&(F0.key!=null&&(l0&&l0.key===F0.key||H(F0.key)),J0=k(F0,J0+(F0.key==null||l0&&l0.key===F0.key?"":(""+F0.key).replace(x0,"$&/")+"/")+BA),N0!==""&&l0!=null&&_(l0)&&l0.key==null&&l0._store&&!l0._store.validated&&(J0._store.validated=2),F0=J0),G0.push(F0)),1}if(l0=0,BA=N0===""?".":N0+":",JA(t))for(var YA=0;YA<t.length;YA++)N0=t[YA],r0=BA+R(N0,YA),l0+=M(N0,G0,J0,r0,F0);else if(YA=Q(t),typeof YA==="function")for(YA===t.entries&&(y0||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),y0=!0),t=YA.call(t),YA=0;!(N0=t.next()).done;)N0=N0.value,r0=BA+R(N0,YA++),l0+=M(N0,G0,J0,r0,F0);else if(r0==="object"){if(typeof t.then==="function")return M(x(t),G0,J0,N0,F0);throw G0=String(t),Error("Objects are not valid as a React child (found: "+(G0==="[object Object]"?"object with keys {"+Object.keys(t).join(", ")+"}":G0)+"). If you meant to render a collection of children, use an array instead.")}return l0}function S(t,G0,J0){if(t==null)return t;var N0=[],F0=0;return M(t,N0,"","",function(r0){return G0.call(J0,r0,F0++)}),N0}function u(t){if(t._status===-1){var G0=t._ioInfo;G0!=null&&(G0.start=G0.end=performance.now()),G0=t._result;var J0=G0();if(J0.then(function(F0){if(t._status===0||t._status===-1){t._status=1,t._result=F0;var r0=t._ioInfo;r0!=null&&(r0.end=performance.now()),J0.status===void 0&&(J0.status="fulfilled",J0.value=F0)}},function(F0){if(t._status===0||t._status===-1){t._status=2,t._result=F0;var r0=t._ioInfo;r0!=null&&(r0.end=performance.now()),J0.status===void 0&&(J0.status="rejected",J0.reason=F0)}}),G0=t._ioInfo,G0!=null){G0.value=J0;var N0=J0.displayName;typeof N0==="string"&&(G0.name=N0)}t._status===-1&&(t._status=0,t._result=J0)}if(t._status===1)return G0=t._result,G0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
|
|
433
|
+
`;await A.session.run(B);let Y=(await A.values(AA`SELECT id, hash, created_at FROM ${AA.identifier($)} ORDER BY created_at DESC LIMIT 1`))[0]??void 0,Z=[];for(let H of w)if(!Y||Number(Y[2])<H.folderMillis){for(let W of H.sql)Z.push(A.run(AA.raw(W)));Z.push(A.run(AA`INSERT INTO ${AA.identifier($)} ("hash", "created_at") VALUES(${H.hash}, ${H.folderMillis})`))}await A.session.migrate(Z)}var Gl=r(()=>{lOA();N9()});async function pOA(A,Q){let w=Q?.child("entity-migrate")??gQ.getInstance().child("entity-migrate"),{db:$,client:B,url:X}=G20(A);w.debug("Running entity database migrations...");try{await D20(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 eF($,{migrationsFolder:Z}),await q20(B),w.debug("Entity database migrations completed successfully")}catch(Y){throw w.error("Entity database migration failed:",Y),Y}finally{B.close()}}var iOA=r(()=>{Gl();lL0();Y7()});async function dOA(A,Q){let w=Q?.child("job-queue-migrate")??gQ.getInstance().child("job-queue-migrate"),{db:$,client:B,url:X}=Z20(A);w.debug("Running job queue migrations...");try{await f20(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 eF($,{migrationsFolder:Z}),w.debug("Job queue migrations completed successfully")}catch(Y){throw w.error("Job queue migration failed:",Y),Y}finally{B.close()}}var nOA=r(()=>{Gl();PL0();Y7()});async function rOA(A,Q){let w=Q?.child("conversation-migrate")??gQ.getInstance().child("conversation-migrate"),{db:$,client:B,url:X}=H20(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 eF($,{migrationsFolder:Z}),w.debug("Conversation database migrations completed successfully")}catch(Y){throw w.error("Conversation database migration failed:",Y),Y}finally{B.close()}}var oOA=r(()=>{Gl();hL0();Y7()});async function sOA(A,Q){let w=Q?.child("runtime-state-migrate")??gQ.getInstance().child("runtime-state-migrate"),{db:$,client:B,url:X}=yw0(A);w.debug("Running runtime state migrations...");try{await gw0(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 eF($,{migrationsFolder:Z}),w.debug("Runtime state migrations completed successfully")}catch(Y){throw w.error("Runtime state migration failed:",Y),Y}finally{B.close()}}var aOA=r(()=>{Gl();Y7();jM0()});import{mkdir as iM0}from"fs/promises";function pw0(A=process.env){return{dataDir:A.XDG_DATA_HOME??"./data",cacheDir:A.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function iw0(A=process.env){return uF(pw0(A))}async function dw0(A=process.env){let Q=pw0(A);try{await iM0(Q.dataDir,{recursive:!0}),await iM0(Q.cacheDir,{recursive:!0}),await iM0(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 uF(Q)}var nw0=r(()=>{cw0()});class Dl{logger;migrations;constructor(A,Q){this.logger=A,this.migrations=Q??{getStandardConfigWithDirectories:()=>dw0(),migrateEntities:pOA,migrateJobQueue:dOA,migrateConversations:rOA,migrateRuntimeState:sOA}}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 dM0=r(()=>{iOA();nOA();oOA();aOA();nw0()});function za2(){return process.env[qa2]}function tOA(){return za2()!=="production"}var qa2="NODE_ENV";var rw0;var nM0=r(()=>{C0();rw0=f.object({theme:f.object({primaryColor:f.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:f.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})})});var AxA;var eOA=r(()=>{AxA={name:"@brains/chat-repl",version:"0.2.0-alpha.169",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 Gw=h((Ja2,ow0)=>{(function(){function A(t,G0){Object.defineProperty($.prototype,t,{get:function(){console.warn("%s(...) is deprecated in plain JavaScript React classes. %s",G0[0],G0[1])}})}function Q(t){if(t===null||typeof t!=="object")return null;return t=j0&&t[j0]||t["@@iterator"],typeof t==="function"?t:null}function w(t,G0){t=(t=t.constructor)&&(t.displayName||t.name)||"ReactClass";var J0=t+"."+G0;P0[J0]||(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.",G0,t),P0[J0]=!0)}function $(t,G0,J0){this.props=t,this.context=G0,this.refs=n0,this.updater=J0||E0}function B(){}function X(t,G0,J0){this.props=t,this.context=G0,this.refs=n0,this.updater=J0||E0}function Y(){}function Z(t){return""+t}function H(t){try{Z(t);var G0=!1}catch(F0){G0=!0}if(G0){G0=console;var J0=G0.error,N0=typeof Symbol==="function"&&Symbol.toStringTag&&t[Symbol.toStringTag]||t.constructor.name||"Object";return J0.call(G0,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",N0),Z(t)}}function W(t){if(t==null)return null;if(typeof t==="function")return t.$$typeof===HA?null:t.displayName||t.name||null;if(typeof t==="string")return t;switch(t){case D0:return"Fragment";case f0:return"Profiler";case T:return"StrictMode";case i0:return"Suspense";case k0:return"SuspenseList";case S0:return"Activity"}if(typeof t==="object")switch(typeof t.tag==="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),t.$$typeof){case a:return"Portal";case i:return t.displayName||"Context";case b0:return(t._context.displayName||"Context")+".Consumer";case u0:var G0=t.render;return t=t.displayName,t||(t=G0.displayName||G0.name||"",t=t!==""?"ForwardRef("+t+")":"ForwardRef"),t;case _0:return G0=t.displayName||null,G0!==null?G0:W(t.type)||"Memo";case v0:G0=t._payload,t=t._init;try{return W(t(G0))}catch(J0){}}return null}function K(t){if(t===D0)return"<>";if(typeof t==="object"&&t!==null&&t.$$typeof===v0)return"<...>";try{var G0=W(t);return G0?"<"+G0+">":"<...>"}catch(J0){return"<...>"}}function U(){var t=WA.A;return t===null?null:t.getOwner()}function G(){return Error("react-stack-top-frame")}function q(t){if(o0.call(t,"key")){var G0=Object.getOwnPropertyDescriptor(t,"key").get;if(G0&&G0.isReactWarning)return!1}return t.key!==void 0}function V(t,G0){function J0(){GA||(GA=!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)",G0))}J0.isReactWarning=!0,Object.defineProperty(t,"key",{get:J0,configurable:!0})}function J(){var t=W(this.type);return RA[t]||(RA[t]=!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.")),t=this.props.ref,t!==void 0?t:null}function F(t,G0,J0,N0,F0,r0){var l0=J0.ref;return t={$$typeof:s,type:t,key:G0,props:J0,_owner:N0},(l0!==void 0?l0:null)!==null?Object.defineProperty(t,"ref",{enumerable:!1,get:J}):Object.defineProperty(t,"ref",{enumerable:!1,value:null}),t._store={},Object.defineProperty(t._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(t,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(t,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:F0}),Object.defineProperty(t,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:r0}),Object.freeze&&(Object.freeze(t.props),Object.freeze(t)),t}function k(t,G0){return G0=F(t.type,G0,t.props,t._owner,t._debugStack,t._debugTask),t._store&&(G0._store.validated=t._store.validated),G0}function j(t){_(t)?t._store&&(t._store.validated=1):typeof t==="object"&&t!==null&&t.$$typeof===v0&&(t._payload.status==="fulfilled"?_(t._payload.value)&&t._payload.value._store&&(t._payload.value._store.validated=1):t._store&&(t._store.validated=1))}function _(t){return typeof t==="object"&&t!==null&&t.$$typeof===s}function O(t){var G0={"=":"=0",":":"=2"};return"$"+t.replace(/[=:]/g,function(J0){return G0[J0]})}function R(t,G0){return typeof t==="object"&&t!==null&&t.key!=null?(H(t.key),O(""+t.key)):G0.toString(36)}function x(t){switch(t.status){case"fulfilled":return t.value;case"rejected":throw t.reason;default:switch(typeof t.status==="string"?t.then(Y,Y):(t.status="pending",t.then(function(G0){t.status==="pending"&&(t.status="fulfilled",t.value=G0)},function(G0){t.status==="pending"&&(t.status="rejected",t.reason=G0)})),t.status){case"fulfilled":return t.value;case"rejected":throw t.reason}}throw t}function M(t,G0,J0,N0,F0){var r0=typeof t;if(r0==="undefined"||r0==="boolean")t=null;var l0=!1;if(t===null)l0=!0;else switch(r0){case"bigint":case"string":case"number":l0=!0;break;case"object":switch(t.$$typeof){case s:case a:l0=!0;break;case v0:return l0=t._init,M(l0(t._payload),G0,J0,N0,F0)}}if(l0){l0=t,F0=F0(l0);var BA=N0===""?"."+R(l0,0):N0;return JA(F0)?(J0="",BA!=null&&(J0=BA.replace(x0,"$&/")+"/"),M(F0,G0,J0,"",function(hA){return hA})):F0!=null&&(_(F0)&&(F0.key!=null&&(l0&&l0.key===F0.key||H(F0.key)),J0=k(F0,J0+(F0.key==null||l0&&l0.key===F0.key?"":(""+F0.key).replace(x0,"$&/")+"/")+BA),N0!==""&&l0!=null&&_(l0)&&l0.key==null&&l0._store&&!l0._store.validated&&(J0._store.validated=2),F0=J0),G0.push(F0)),1}if(l0=0,BA=N0===""?".":N0+":",JA(t))for(var YA=0;YA<t.length;YA++)N0=t[YA],r0=BA+R(N0,YA),l0+=M(N0,G0,J0,r0,F0);else if(YA=Q(t),typeof YA==="function")for(YA===t.entries&&(y0||console.warn("Using Maps as children is not supported. Use an array of keyed ReactElements instead."),y0=!0),t=YA.call(t),YA=0;!(N0=t.next()).done;)N0=N0.value,r0=BA+R(N0,YA++),l0+=M(N0,G0,J0,r0,F0);else if(r0==="object"){if(typeof t.then==="function")return M(x(t),G0,J0,N0,F0);throw G0=String(t),Error("Objects are not valid as a React child (found: "+(G0==="[object Object]"?"object with keys {"+Object.keys(t).join(", ")+"}":G0)+"). If you meant to render a collection of children, use an array instead.")}return l0}function S(t,G0,J0){if(t==null)return t;var N0=[],F0=0;return M(t,N0,"","",function(r0){return G0.call(J0,r0,F0++)}),N0}function u(t){if(t._status===-1){var G0=t._ioInfo;G0!=null&&(G0.start=G0.end=performance.now()),G0=t._result;var J0=G0();if(J0.then(function(F0){if(t._status===0||t._status===-1){t._status=1,t._result=F0;var r0=t._ioInfo;r0!=null&&(r0.end=performance.now()),J0.status===void 0&&(J0.status="fulfilled",J0.value=F0)}},function(F0){if(t._status===0||t._status===-1){t._status=2,t._result=F0;var r0=t._ioInfo;r0!=null&&(r0.end=performance.now()),J0.status===void 0&&(J0.status="rejected",J0.reason=F0)}}),G0=t._ioInfo,G0!=null){G0.value=J0;var N0=J0.displayName;typeof N0==="string"&&(G0.name=N0)}t._status===-1&&(t._status=0,t._result=J0)}if(t._status===1)return G0=t._result,G0===void 0&&console.error(`lazy: Expected the result of a dynamic import() call. Instead received: %s
|
|
434
434
|
|
|
435
435
|
Your code should look like:
|
|
436
436
|
const MyComponent = lazy(() => import('./MyComponent'))
|
|
@@ -1717,7 +1717,7 @@ Example bad output: "A dreamlike crystal formation glowing with ethereal light i
|
|
|
1717
1717
|
Title: "${A.entityTitle??Z}"
|
|
1718
1718
|
|
|
1719
1719
|
Content:
|
|
1720
|
-
${K}`,CQQ);W=`${$.trim()} ${k.imagePrompt}`}catch(k){this.logger.warn("AI prompt distillation failed, using fallback",{error:dA(k)})}}await this.reportProgress(w,{progress:Zw.PROCESS,message:"Generating image"});let U=this.context.identity.get(),G=this.context.identity.getProfile(),V=OgA(U,G)+W,J;try{J=await this.context.ai.generateImage(V,{...B&&{aspectRatio:B}})}catch(k){return this.logger.error("Image generation failed",{jobId:Q,error:dA(k)}),j8.failure(k)}await this.reportProgress(w,{progress:Zw.GENERATE,message:"Creating image entity"});let F=bf.createImageEntity({dataUrl:J.dataUrl,title:Z,status:"draft",attachmentType:"generated",...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}});if(await rX({entityService:this.context.entityService,entity:{...F,id:H}}),this.logger.debug("Created image entity",{imageId:H}),X&&Y){await this.reportProgress(w,{progress:Zw.SAVE,message:`Updating ${X} with cover image`});let k=await P_(this.context.entityService,X,Y,this.logger);if(!k)return j8.failure(Error(`Target entity not found: ${X}/${Y}`));let j=BN(k,H);await this.context.entities.update(j),this.logger.debug("Updated target entity with cover image",{targetEntityType:X,targetEntityId:Y,imageId:H})}return await this.reportProgress(w,{progress:Zw.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:H,targetEntityType:X,targetEntityId:Y}),{success:!0,imageId:H}}catch(W){let K=dA(W);return this.logger.error("Image generation job failed",{jobId:Q,error:K}),await KD({entityService:this.context.entityService,entityType:"image",id:H,error:K}),j8.failure(W)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}fA();C0();Q$();r4();var gQQ=f.object({sourceEntityType:f.string().min(1),sourceEntityId:f.string().min(1),attachmentType:f.string().min(1),imageId:f.string().min(1),dedupKey:f.string().min(1).optional(),replace:f.boolean().optional(),targetEntityType:f.string().min(1).optional(),targetEntityId:f.string().min(1).optional(),targetImageField:f.enum(["coverImageId","ogImageId"]).optional()});class zR0 extends z6{context;constructor(A,Q){super(Q,{schema:gQQ,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:Zw.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:Y.id,reused:!0}}await this.reportProgress(w,{progress:Zw.PROCESS,message:"Rendering source image"});let $=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!$)return j8.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if($.type!=="image")return j8.failure(Error(`Attachment provider returned ${$.type}; expected image`));await this.reportProgress(w,{progress:Zw.GENERATE,message:"Creating image entity"});let B=$.mimeType.split("/")[1]??"png",X=bf.createImageEntity({dataUrl:EM0($.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 rX({entityService:this.context.entityService,entity:{...X,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress(w,{progress:Zw.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch($){let B=dA($);return this.logger.error("Source image render job failed",{jobId:Q,error:B}),await KD({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:B}),j8.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 P_(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"?Kl(w,Q):BN(w,Q);await this.context.entities.update(B)}}fA();C0();Q$();r4();k2();var Hh={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function F$0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function I$0(A){let Q=EQQ(A.title,A.filename),w=q1(Q);if(!w)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:w,title:Q}}function xgA(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function EQQ(A,Q){let w=A?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}var TQQ=f.object({uploadId:f.string().min(1),imageId:f.string().min(1).optional(),title:f.string().optional()});class VR0 extends z6{context;constructor(A,Q){super(A,{schema:TQQ,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(Hh).read(A.uploadId);if(!F$0($.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let B=I$0({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=bf.createImageEntity({dataUrl:xgA($.record.mediaType,$.content),title:B.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:$.record.filename,sourceMediaType:$.record.mediaType,attachmentType:"uploaded"}),H=await rX({entityService:this.context.entityService,entity:{id:X,...Z,created:Y,updated:Y}});return await this.reportProgress(w,{progress:100,message:"Uploaded image promoted"}),{entityId:H.entityId,status:"created"}}catch($){if(A.imageId)await KD({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:dA($)});return j8.failure($)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var RgA={name:"@brains/image-plugin",version:"0.2.0-alpha.168",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 mQQ="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",uQQ=f.object({defaultAspectRatio:f.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function JU(A){let Q=A?.trim();if(!Q)return;return Q}function cQQ(A){let Q=JU(A.prompt);if(Q)return Q;let w=JU(A.content);if(w&&!qR0(w))return w;return}function lQQ(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return q1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function vgA(A){let Q=JU(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return q1(Q)}async function pQQ(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 JR0(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 iQQ(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 FR0 extends fw{entityType=bf.entityType;schema=Hl;adapter=bf;constructor(A={}){super("image",RgA,A,uQQ)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,w){if(A.from?.kind===Hh.refKind)return this.promoteUpload(A,w);let $=cQQ(A),B=JU(A.targetEntityType),X=JU(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 G=JU(A.title)??Y,q=vgA({prompt:$,...G&&{title:G}});await this.createPendingImage(w,{id:q,title:G??$.slice(0,60).trim(),alt:G??$.slice(0,60).trim(),attachmentType:"generated"});let V=await w.jobs.enqueue({type:"image-generate",data:{prompt:$,...G&&{title:G}}});return{kind:"handled",result:{success:!0,data:{entityId:q,status:"generating",jobId:V,attachment:JR0(q)}}}}let H=await c4(w.entityService,B,X,this.logger,"Target entity");if(!H.ok)return{kind:"handled",result:{success:!1,error:H.error}};if(!$)return{kind:"continue",input:{...A,targetEntityId:H.entity.id}};let W=V$0(H.entity.content),K=vgA({prompt:$,...A.title&&{title:A.title},targetEntityId:H.entity.id});await this.createPendingImage(w,{id:K,title:A.title??`cover-${H.entity.id}`,alt:A.title??`cover-${H.entity.id}`,attachmentType:"generated",sourceEntityType:B,sourceEntityId:H.entity.id});let U=await w.jobs.enqueue({type:"image-generate",data:{prompt:$,...A.title&&{title:A.title},targetEntityType:B,targetEntityId:H.entity.id,entityTitle:typeof H.entity.metadata.title==="string"?H.entity.metadata.title:H.entity.id,...W&&{entityContent:W}}});return{kind:"handled",result:{success:!0,data:{entityId:K,status:"generating",jobId:U,attachment:JR0(K)}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==Hh.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let $=w.id,B;try{B=await Q.uploads.scoped(Hh).readRecord($)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!F$0(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let X;try{X=I$0({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:iQQ({mediaType:B.mediaType,entityId:X.id,filename:B.filename})}}}}async enqueueSourceImageRender(A,Q){let w=JU(A.from.sourceEntityType),$=JU(A.from.sourceEntityId),B=JU(A.from.attachmentType);if(!w||!$||!B)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let X=await c4(Q.entityService,w,$,this.logger,"Source entity");if(!X.ok)return{kind:"handled",result:{success:!1,error:X.error}};let Y=JU(A.targetEntityType),Z=JU(A.targetEntityId),H;if(Y&&Z){let q=await c4(Q.entityService,Y,Z,this.logger,"Target entity");if(!q.ok)return{kind:"handled",result:{success:!1,error:q.error}};H=q.entity.id}let W={sourceEntityType:w,sourceEntityId:X.entity.id,attachmentType:B},K=await pQQ(Q,W),U=lQQ(W);await this.createPendingImage(Q,{id:U,title:U,alt:U,sourceEntityType:W.sourceEntityType,sourceEntityId:W.sourceEntityId,attachmentType:B,dedupKey:K});let G=await Q.jobs.enqueue({type:"image-render-source",data:{...W,imageId:U,dedupKey:K,...A.replace===!0&&{replace:!0},...Y&&{targetEntityType:Y},...H&&{targetEntityId:H},...B==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:U,status:"generating",jobId:G,attachment:JR0(U,B)}}}}async createPendingImage(A,Q){let w=new Date().toISOString(),$=bf.createImageEntity({dataUrl:mQQ,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 O_({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 J$0(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 J$0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new zR0(A,this.logger)),A.jobs.registerHandler("upload-promote",new VR0(this.logger.child("UploadPromotionJobHandler"),A))}}function Gp(A={}){return new FR0(A)}fA();import{StdioServerTransport as nQQ}from"@modelcontextprotocol/sdk/server/stdio.js";C0();var dQQ=f.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 hgA(){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 IR0(){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 b$0(A){let Q=dQQ.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 IR0()}class FU{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return FU.instance??=new FU(A),FU.instance}static resetInstance(){if(FU.instance)FU.instance.stop(),FU.instance=null}static createFresh(A){return new FU(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?b$0(this.config.logger):hgA()}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 nQQ,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 rQQ,timingSafeEqual as oQQ}from"crypto";import{WebStandardStreamableHTTPServerTransport as sQQ}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as aQQ}from"@modelcontextprotocol/sdk/types.js";C0();var tQQ=1800000,eQQ=60000,AwQ={"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"},QwQ=f.looseObject({code:f.string().optional()});function wwQ(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 v3{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?b$0(this.config.logger):IR0(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??tQQ,this.evictionTimer=setInterval(()=>this.evictIdleSessions(),Math.min(this.sessionIdleTtlMs,eQQ)),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 v3.instance??=new v3(A),v3.instance}static resetInstance(){v3.instance=null}static createFresh(A){return new v3(A)}withCors(A){let Q=new Headers(A.headers);for(let[w,$]of Object.entries(AwQ))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:`${wwQ(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries(w).map(([B,X])=>`${B}="${$wQ(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(!BwQ($,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&&aQQ($))B=new sQQ({sessionIdGenerator:()=>rQQ(),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 $=QwQ.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 $wQ(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function BwQ(A,Q){let w=Buffer.from(A),$=Buffer.from(Q);if(w.length!==$.length)return!1;return oQQ(w,$)}import{randomUUID as KwQ}from"crypto";import{chmod as XwQ,mkdir as YwQ,readFile as ZwQ,rename as CgA,writeFile as fwQ}from"fs/promises";import{dirname as HwQ}from"path";class wY{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 ZwQ(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 YwQ(HwQ(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await fwQ(Q,`${JSON.stringify(A,null,2)}
|
|
1720
|
+
${K}`,CQQ);W=`${$.trim()} ${k.imagePrompt}`}catch(k){this.logger.warn("AI prompt distillation failed, using fallback",{error:dA(k)})}}await this.reportProgress(w,{progress:Zw.PROCESS,message:"Generating image"});let U=this.context.identity.get(),G=this.context.identity.getProfile(),V=OgA(U,G)+W,J;try{J=await this.context.ai.generateImage(V,{...B&&{aspectRatio:B}})}catch(k){return this.logger.error("Image generation failed",{jobId:Q,error:dA(k)}),j8.failure(k)}await this.reportProgress(w,{progress:Zw.GENERATE,message:"Creating image entity"});let F=bf.createImageEntity({dataUrl:J.dataUrl,title:Z,status:"draft",attachmentType:"generated",...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}});if(await rX({entityService:this.context.entityService,entity:{...F,id:H}}),this.logger.debug("Created image entity",{imageId:H}),X&&Y){await this.reportProgress(w,{progress:Zw.SAVE,message:`Updating ${X} with cover image`});let k=await P_(this.context.entityService,X,Y,this.logger);if(!k)return j8.failure(Error(`Target entity not found: ${X}/${Y}`));let j=BN(k,H);await this.context.entities.update(j),this.logger.debug("Updated target entity with cover image",{targetEntityType:X,targetEntityId:Y,imageId:H})}return await this.reportProgress(w,{progress:Zw.COMPLETE,message:"Image generation complete"}),this.logger.info("Image generation job complete",{jobId:Q,imageId:H,targetEntityType:X,targetEntityId:Y}),{success:!0,imageId:H}}catch(W){let K=dA(W);return this.logger.error("Image generation job failed",{jobId:Q,error:K}),await KD({entityService:this.context.entityService,entityType:"image",id:H,error:K}),j8.failure(W)}}summarizeDataForLog(A){return{title:A.title,promptLength:A.prompt.length,aspectRatio:A.aspectRatio,targetEntityType:A.targetEntityType,targetEntityId:A.targetEntityId}}}fA();C0();Q$();r4();var gQQ=f.object({sourceEntityType:f.string().min(1),sourceEntityId:f.string().min(1),attachmentType:f.string().min(1),imageId:f.string().min(1),dedupKey:f.string().min(1).optional(),replace:f.boolean().optional(),targetEntityType:f.string().min(1).optional(),targetEntityId:f.string().min(1).optional(),targetImageField:f.enum(["coverImageId","ogImageId"]).optional()});class zR0 extends z6{context;constructor(A,Q){super(Q,{schema:gQQ,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:Zw.COMPLETE,message:"Reusing existing generated image"}),{success:!0,imageId:Y.id,reused:!0}}await this.reportProgress(w,{progress:Zw.PROCESS,message:"Rendering source image"});let $=await this.context.attachments.resolve({sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType});if(!$)return j8.failure(Error(`No attachment provider found for ${A.sourceEntityType}/${A.attachmentType}`));if($.type!=="image")return j8.failure(Error(`Attachment provider returned ${$.type}; expected image`));await this.reportProgress(w,{progress:Zw.GENERATE,message:"Creating image entity"});let B=$.mimeType.split("/")[1]??"png",X=bf.createImageEntity({dataUrl:EM0($.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 rX({entityService:this.context.entityService,entity:{...X,id:A.imageId}}),await this.updateTarget(A,A.imageId),await this.reportProgress(w,{progress:Zw.COMPLETE,message:"Image render complete"}),{success:!0,imageId:A.imageId,reused:!1}}catch($){let B=dA($);return this.logger.error("Source image render job failed",{jobId:Q,error:B}),await KD({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:B}),j8.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 P_(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"?Kl(w,Q):BN(w,Q);await this.context.entities.update(B)}}fA();C0();Q$();r4();k2();var Hh={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function F$0(A){return["image/png","image/jpeg","image/webp","image/gif"].includes(A.toLowerCase())}function I$0(A){let Q=EQQ(A.title,A.filename),w=q1(Q);if(!w)throw Error("Could not derive an image id from the uploaded filename. Provide a title.");return{id:w,title:Q}}function xgA(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function EQQ(A,Q){let w=A?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}var TQQ=f.object({uploadId:f.string().min(1),imageId:f.string().min(1).optional(),title:f.string().optional()});class VR0 extends z6{context;constructor(A,Q){super(A,{schema:TQQ,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(Hh).read(A.uploadId);if(!F$0($.record.mediaType))throw Error("Only image uploads can be promoted to image entities");let B=I$0({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=bf.createImageEntity({dataUrl:xgA($.record.mediaType,$.content),title:B.title,status:"draft",sourceUploadId:A.uploadId,sourceFilename:$.record.filename,sourceMediaType:$.record.mediaType,attachmentType:"uploaded"}),H=await rX({entityService:this.context.entityService,entity:{id:X,...Z,created:Y,updated:Y}});return await this.reportProgress(w,{progress:100,message:"Uploaded image promoted"}),{entityId:H.entityId,status:"created"}}catch($){if(A.imageId)await KD({entityService:this.context.entityService,entityType:"image",id:A.imageId,error:dA($)});return j8.failure($)}}summarizeDataForLog(A){return{uploadId:A.uploadId,imageId:A.imageId,hasTitle:A.title!==void 0}}}var RgA={name:"@brains/image-plugin",version:"0.2.0-alpha.169",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 mQQ="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",uQQ=f.object({defaultAspectRatio:f.enum(["1:1","16:9","9:16","4:3","3:4"]).default("16:9").describe("Default aspect ratio for generated images")});function JU(A){let Q=A?.trim();if(!Q)return;return Q}function cQQ(A){let Q=JU(A.prompt);if(Q)return Q;let w=JU(A.content);if(w&&!qR0(w))return w;return}function lQQ(A){let Q=A.attachmentType==="og-image"?"og":A.attachmentType;return q1(`${Q}-${A.sourceEntityType}-${A.sourceEntityId}`)}function vgA(A){let Q=JU(A.title)??(A.targetEntityId?`cover-${A.targetEntityId}`:A.prompt.slice(0,60).trim());return q1(Q)}async function pQQ(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 JR0(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 iQQ(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 FR0 extends fw{entityType=bf.entityType;schema=Hl;adapter=bf;constructor(A={}){super("image",RgA,A,uQQ)}getEntityTypeConfig(){return{embeddable:!1}}async interceptCreate(A,Q,w){if(A.from?.kind===Hh.refKind)return this.promoteUpload(A,w);let $=cQQ(A),B=JU(A.targetEntityType),X=JU(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 G=JU(A.title)??Y,q=vgA({prompt:$,...G&&{title:G}});await this.createPendingImage(w,{id:q,title:G??$.slice(0,60).trim(),alt:G??$.slice(0,60).trim(),attachmentType:"generated"});let V=await w.jobs.enqueue({type:"image-generate",data:{prompt:$,...G&&{title:G}}});return{kind:"handled",result:{success:!0,data:{entityId:q,status:"generating",jobId:V,attachment:JR0(q)}}}}let H=await c4(w.entityService,B,X,this.logger,"Target entity");if(!H.ok)return{kind:"handled",result:{success:!1,error:H.error}};if(!$)return{kind:"continue",input:{...A,targetEntityId:H.entity.id}};let W=V$0(H.entity.content),K=vgA({prompt:$,...A.title&&{title:A.title},targetEntityId:H.entity.id});await this.createPendingImage(w,{id:K,title:A.title??`cover-${H.entity.id}`,alt:A.title??`cover-${H.entity.id}`,attachmentType:"generated",sourceEntityType:B,sourceEntityId:H.entity.id});let U=await w.jobs.enqueue({type:"image-generate",data:{prompt:$,...A.title&&{title:A.title},targetEntityType:B,targetEntityId:H.entity.id,entityTitle:typeof H.entity.metadata.title==="string"?H.entity.metadata.title:H.entity.id,...W&&{entityContent:W}}});return{kind:"handled",result:{success:!0,data:{entityId:K,status:"generating",jobId:U,attachment:JR0(K)}}}}async promoteUpload(A,Q){let w=A.from;if(w?.kind!==Hh.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let $=w.id,B;try{B=await Q.uploads.scoped(Hh).readRecord($)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}if(!F$0(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only image uploads can be promoted to image entities"}};let X;try{X=I$0({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:iQQ({mediaType:B.mediaType,entityId:X.id,filename:B.filename})}}}}async enqueueSourceImageRender(A,Q){let w=JU(A.from.sourceEntityType),$=JU(A.from.sourceEntityId),B=JU(A.from.attachmentType);if(!w||!$||!B)return{kind:"handled",result:{success:!1,error:"Image source requires sourceEntityType, sourceEntityId, and attachmentType"}};let X=await c4(Q.entityService,w,$,this.logger,"Source entity");if(!X.ok)return{kind:"handled",result:{success:!1,error:X.error}};let Y=JU(A.targetEntityType),Z=JU(A.targetEntityId),H;if(Y&&Z){let q=await c4(Q.entityService,Y,Z,this.logger,"Target entity");if(!q.ok)return{kind:"handled",result:{success:!1,error:q.error}};H=q.entity.id}let W={sourceEntityType:w,sourceEntityId:X.entity.id,attachmentType:B},K=await pQQ(Q,W),U=lQQ(W);await this.createPendingImage(Q,{id:U,title:U,alt:U,sourceEntityType:W.sourceEntityType,sourceEntityId:W.sourceEntityId,attachmentType:B,dedupKey:K});let G=await Q.jobs.enqueue({type:"image-render-source",data:{...W,imageId:U,dedupKey:K,...A.replace===!0&&{replace:!0},...Y&&{targetEntityType:Y},...H&&{targetEntityId:H},...B==="og-image"&&{targetImageField:"ogImageId"}}});return{kind:"handled",result:{success:!0,data:{entityId:U,status:"generating",jobId:G,attachment:JR0(U,B)}}}}async createPendingImage(A,Q){let w=new Date().toISOString(),$=bf.createImageEntity({dataUrl:mQQ,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 O_({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 J$0(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 J$0(A,this.logger);A.jobs.registerHandler("image-generate",Q),A.jobs.registerHandler("image-render-source",new zR0(A,this.logger)),A.jobs.registerHandler("upload-promote",new VR0(this.logger.child("UploadPromotionJobHandler"),A))}}function Gp(A={}){return new FR0(A)}fA();import{StdioServerTransport as nQQ}from"@modelcontextprotocol/sdk/server/stdio.js";C0();var dQQ=f.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 hgA(){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 IR0(){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 b$0(A){let Q=dQQ.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 IR0()}class FU{static instance=null;mcpServer=null;transport=null;config;logger;static getInstance(A){return FU.instance??=new FU(A),FU.instance}static resetInstance(){if(FU.instance)FU.instance.stop(),FU.instance=null}static createFresh(A){return new FU(A)}constructor(A={}){this.config=A,this.logger=this.config.logger?b$0(this.config.logger):hgA()}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 nQQ,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 rQQ,timingSafeEqual as oQQ}from"crypto";import{WebStandardStreamableHTTPServerTransport as sQQ}from"@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";import{isInitializeRequest as aQQ}from"@modelcontextprotocol/sdk/types.js";C0();var tQQ=1800000,eQQ=60000,AwQ={"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"},QwQ=f.looseObject({code:f.string().optional()});function wwQ(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 v3{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?b$0(this.config.logger):IR0(),this.authConfig=A.auth??{},this.sessionIdleTtlMs=A.sessionIdleTtlMs??tQQ,this.evictionTimer=setInterval(()=>this.evictIdleSessions(),Math.min(this.sessionIdleTtlMs,eQQ)),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 v3.instance??=new v3(A),v3.instance}static resetInstance(){v3.instance=null}static createFresh(A){return new v3(A)}withCors(A){let Q=new Headers(A.headers);for(let[w,$]of Object.entries(AwQ))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:`${wwQ(A)}/.well-known/oauth-protected-resource`},...Q};return`Bearer ${Object.entries(w).map(([B,X])=>`${B}="${$wQ(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(!BwQ($,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&&aQQ($))B=new sQQ({sessionIdGenerator:()=>rQQ(),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 $=QwQ.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 $wQ(A){return A.replace(/["\\]/g,(Q)=>`\\${Q}`)}function BwQ(A,Q){let w=Buffer.from(A),$=Buffer.from(Q);if(w.length!==$.length)return!1;return oQQ(w,$)}import{randomUUID as KwQ}from"crypto";import{chmod as XwQ,mkdir as YwQ,readFile as ZwQ,rename as CgA,writeFile as fwQ}from"fs/promises";import{dirname as HwQ}from"path";class wY{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 ZwQ(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 YwQ(HwQ(this.filePath),{recursive:!0,mode:448});let Q=`${this.filePath}.tmp`;await fwQ(Q,`${JSON.stringify(A,null,2)}
|
|
1721
1721
|
`,{mode:384}),await XwQ(Q,384),await CgA(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 CgA(this.filePath,Q)}catch(w){this.logError(`Failed to quarantine corrupt JSON store at ${this.filePath}`,w)}}}function Wh(A){let Q=A.toISOString();return Q.substring(0,Q.indexOf("T"))}function L$0(){let A=new Date;return A.setDate(A.getDate()-1),A}function ygA(A){let Q=new Date;return Q.setDate(Q.getDate()-A),Q}function v9(){return Math.floor(Date.now()/1000)}C0();import{join as UwQ}from"path";function ggA(A){let Q=A.toLowerCase();return Q==="localhost"||Q==="[::1]"||Q==="::1"||Q.startsWith("127.")}function EgA(A){try{return new URL(A)}catch{return}}function bR0(A,Q){if(A===Q)return!0;let w=EgA(A),$=EgA(Q);if(!w||!$)return!1;if(!ggA(w.hostname)||!ggA($.hostname))return!1;return w.protocol===$.protocol&&w.port===$.port&&WwQ(w.pathname,$.pathname)&&w.search===$.search&&w.hash===$.hash}function WwQ(A,Q){return A===Q||A===`${Q}/debug`||Q===`${A}/debug`}function LR0(A,Q){return A.some((w)=>bR0(w,Q))}var GwQ="oauth-auth-codes.json",DwQ=600,qwQ=f.looseObject({code:f.string(),client_id:f.string(),redirect_uri:f.string(),code_challenge:f.string(),code_challenge_method:f.literal("S256"),scope:f.string().optional(),subject:f.string(),created_at:f.number(),expires_at:f.number(),consumed_at:f.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}:{}})),zwQ=f.looseObject({codes:f.array(f.unknown()).optional()});function VwQ(A){let Q=zwQ.safeParse(A);if(!Q.success)return{codes:[]};return{codes:Q.data.codes?.flatMap(JwQ)??[]}}function JwQ(A){let Q=qwQ.safeParse(A);return Q.success?[Q.data]:[]}async function FwQ(A){let Q=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(A));return Buffer.from(Q).toString("base64url")}class k$0{store;constructor(A){this.store=new wY({filePath:UwQ(A.storageDir,A.storeFile??GwQ),parse:VwQ,empty:()=>({codes:[]})})}async createCode(A){let Q=v9(),w={code:`ocd_${KwQ()}`,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+DwQ};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=v9(),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 IU("Authorization code not found");if(X.consumed_at!==void 0)throw new IU("Authorization code already consumed");if(X.expires_at<=Q)throw new IU("Authorization code expired");if(X.client_id!==A.clientId)throw new IU("Authorization code client mismatch");if(!bR0(X.redirect_uri,A.redirectUri))throw new IU("Authorization code redirect URI mismatch");let Y=await FwQ(A.codeVerifier);if(X.code_challenge!==Y)throw new IU("PKCE verification failed");w={...X,consumed_at:Q},$.codes[B]=w,await this.store.write($)}),!w)throw new IU("Authorization code not consumed");return w}}class IU extends Error{constructor(A){super(A);this.name="InvalidGrantError"}}import{randomUUID as TgA}from"crypto";C0();import{join as IwQ}from"path";var bwQ="oauth-clients.json",LwQ=f.enum(["none","client_secret_basic","client_secret_post"]),kwQ=f.object({redirect_uris:f.array(f.url()).min(1),token_endpoint_auth_method:LwQ.default("none"),grant_types:f.array(f.enum(["authorization_code","refresh_token"])).default(["authorization_code","refresh_token"]),response_types:f.array(f.literal("code")).default(["code"]),scope:f.string().optional(),client_name:f.string().optional(),client_uri:f.url().optional(),logo_uri:f.url().optional(),contacts:f.array(f.string()).optional()}),_wQ=f.looseObject({client_id:f.string(),client_id_issued_at:f.number(),redirect_uris:f.array(f.string()),token_endpoint_auth_method:f.string().optional(),grant_types:f.array(f.string()).optional(),response_types:f.array(f.string()).optional(),scope:f.string().optional(),client_name:f.string().optional(),client_uri:f.string().optional(),logo_uri:f.string().optional(),contacts:f.array(f.string()).optional(),client_secret:f.string().optional(),client_secret_expires_at:f.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}:{}})),NwQ=f.looseObject({clients:f.array(f.unknown()).optional()});function jwQ(){return`ocs_${TgA().replaceAll("-","")}`}function PwQ(A){let Q=NwQ.safeParse(A);if(!Q.success)return{clients:[]};return{clients:Q.data.clients?.flatMap(MwQ)??[]}}function MwQ(A){let Q=_wQ.safeParse(A);return Q.success?[Q.data]:[]}class _$0{store;constructor(A){this.store=new wY({filePath:IwQ(A.storageDir,A.storeFile??bwQ),parse:PwQ,empty:()=>({clients:[]})})}async registerClient(A){let Q=kwQ.safeParse(A);if(!Q.success)throw new Dp(Q.error.message);let w=Q.data,$=v9(),B=`oc_${TgA()}`,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:jwQ(),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 Dp extends Error{constructor(A){super(A);this.name="InvalidClientMetadataError"}}C0();import{createHash as SgA,generateKeyPairSync as OwQ}from"crypto";import{mkdir as xwQ,readFile as mgA,writeFile as RwQ,chmod as vwQ}from"fs/promises";import{dirname as hwQ,join as ugA}from"path";var CwQ="oauth-signing-key.jwk",ywQ="a2a-signing-key.jwk",cgA=f.object({kty:f.literal("EC"),crv:f.literal("P-256"),x:f.string(),y:f.string(),d:f.string(),kid:f.string().optional()}),lgA=f.object({kty:f.literal("OKP"),crv:f.literal("Ed25519"),x:f.string(),d:f.string(),kid:f.string().optional()});function gwQ(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x,y:A.y});return SgA("sha256").update(Q).digest("base64url")}function EwQ(A){let Q=JSON.stringify({crv:A.crv,kty:A.kty,x:A.x});return SgA("sha256").update(Q).digest("base64url")}function TwQ(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,kid:A.kid,use:"sig",alg:"ES256"}}function SwQ(A){return{kty:"OKP",crv:"Ed25519",x:A.x,kid:A.kid,use:"sig",alg:"EdDSA"}}async function mwQ(){let A=await crypto.subtle.generateKey({name:"ECDSA",namedCurve:"P-256"},!0,["sign","verify"]),Q=cgA.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 pgA(Q.data)}function uwQ(){let{privateKey:A}=OwQ("ed25519"),Q=lgA.safeParse(A.export({format:"jwk"}));if(!Q.success)throw Error("Generated A2A signing key is not an Ed25519 private JWK");return igA(Q.data)}function pgA(A){return{kty:"EC",crv:"P-256",x:A.x,y:A.y,d:A.d,kid:A.kid??gwQ(A),use:"sig",alg:"ES256"}}function igA(A){return{kty:"OKP",crv:"Ed25519",x:A.x,d:A.d,kid:A.kid??EwQ(A),use:"sig",alg:"EdDSA"}}class N$0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=ugA(A.storageDir,A.keyFile??CwQ)}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 mwQ();return await dgA(this.keyFile,Q),Q}async getPublicJwk(){return TwQ(await this.getPrivateJwk())}async readExistingKey(){try{let A=cgA.safeParse(JSON.parse(await mgA(this.keyFile,"utf8")));if(!A.success)throw Error(`OAuth signing key at ${this.keyFile} is not a private P-256 JWK`);return pgA(A.data)}catch(A){if(ngA(A))return;throw A}}}class kR0{keyFile;cachedKey;loadPromise;constructor(A){this.keyFile=ugA(A.storageDir,A.keyFile??ywQ)}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=uwQ();return await dgA(this.keyFile,Q),Q}async getPublicJwk(){return SwQ(await this.getPrivateJwk())}async readExistingKey(){try{let A=lgA.safeParse(JSON.parse(await mgA(this.keyFile,"utf8")));if(!A.success)throw Error(`A2A signing key at ${this.keyFile} is not a private Ed25519 JWK`);return igA(A.data)}catch(A){if(ngA(A))return;throw A}}}async function dgA(A,Q){await xwQ(hwQ(A),{recursive:!0,mode:448}),await RwQ(A,`${JSON.stringify(Q,null,2)}
|
|
1722
1722
|
`,{mode:384}),await vwQ(A,384)}function ngA(A){return A instanceof Error&&"code"in A&&A.code==="ENOENT"}var uQ={};v6(uQ,{trimPadding:()=>ogA,toUTF8String:()=>swQ,toBuffer:()=>dwQ,toBase64:()=>rwQ,isBase64URL:()=>twQ,isBase64:()=>awQ,fromUTF8String:()=>owQ,fromBuffer:()=>nwQ});var rgA=(A)=>{let Q=typeof Uint8Array>"u"?[]:new Uint8Array(256),w=64;for(let $=0;$<64;$++)Q[A.charCodeAt($)]=$;return Q},cwQ=rgA("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),lwQ=rgA("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"),pwQ=/^[-A-Za-z0-9\-_]*$/,iwQ=/^[-A-Za-z0-9+/]*={0,3}$/,MD={};MD.toArrayBuffer=(A,Q)=>{let w=A.length,$=A.length*0.75,B,X=0,Y,Z,H,W;if(A[A.length-1]==="="){if($--,A[A.length-2]==="=")$--}let K=new ArrayBuffer($),U=new Uint8Array(K),G=Q?lwQ:cwQ;for(B=0;B<w;B+=4)Y=G[A.charCodeAt(B)],Z=G[A.charCodeAt(B+1)],H=G[A.charCodeAt(B+2)],W=G[A.charCodeAt(B+3)],U[X++]=Y<<2|Z>>4,U[X++]=(Z&15)<<4|H>>2,U[X++]=(H&3)<<6|W&63;return K};MD.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};MD.toString=(A,Q)=>{return new TextDecoder().decode(MD.toArrayBuffer(A,Q))};MD.fromString=(A,Q)=>{return MD.fromArrayBuffer(new TextEncoder().encode(A),Q)};MD.validate=(A,Q)=>{if(!(typeof A==="string"||A instanceof String))return!1;try{return Q?pwQ.test(A):iwQ.test(A)}catch(w){return!1}};MD.base64=MD;var h3=MD;function dwQ(A,Q="base64url"){let w=h3.toArrayBuffer(A,Q==="base64url");return new Uint8Array(w)}function nwQ(A,Q="base64url"){let w=new Uint8Array(A);return h3.fromArrayBuffer(w.buffer,Q==="base64url")}function rwQ(A){let Q=h3.toArrayBuffer(A,!0);return h3.fromArrayBuffer(Q)}function owQ(A){return h3.fromString(A,!0)}function swQ(A){return h3.toString(A,!0)}function awQ(A){return h3.validate(A,!1)}function twQ(A){return A=ogA(A),h3.validate(A,!0)}function ogA(A){return A.replace(/=/g,"")}var $Y={};v6($Y,{encode:()=>F6Q,decodeFirst:()=>J6Q});function Kh(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 j$0=0,qp=1,_R0=2,NR0=3,jR0=4,PR0=5,MR0=6,sgA=7;function OD(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==qp){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 M$0{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 agA(A,Q,w){return Kh(A,Q,w)}function ewQ(A,Q,w){let[$,B]=agA(A,Q,w);return[-$-1,B]}function tgA(A,Q,w){let[$,B]=Kh(A,Q,w),X=w+B;return[new Uint8Array(A.buffer.slice(X,X+$)),B+$]}var A6Q=new TextDecoder;function Q6Q(A,Q,w){let[$,B]=tgA(A,Q,w);return[A6Q.decode($),B]}function w6Q(A,Q,w){if(Q===0)return[[],1];let[$,B]=Kh(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[W,K]=_N(A,w+X);Y.push(W),X+=K}return[Y,X]}var P$0="Map is not supported or well formed";function $6Q(A,Q,w){if(Q===0)return[new Map,1];let[$,B]=Kh(A,Q,w),X=B,Y=new Map;for(let Z=0;Z<$;Z++){let H=A.byteLength-w-X;if(H<=0)throw Error(P$0);let[W,K]=_N(A,w+X);if(X+=K,H-=K,H<=0)throw Error(P$0);if(typeof W!=="string"&&typeof W!=="number")throw Error(P$0);if(Y.has(W))throw Error(P$0);let[U,G]=_N(A,w+X);X+=G,Y.set(W,U)}return[Y,X]}function B6Q(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 X6Q(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 Y6Q(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 Z6Q(A,Q,w){let[$,B]=Kh(A,Q,w),[X,Y]=_N(A,w+B);return[new M$0($,X),B+Y]}function _N(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 j$0:return agA(A,B,Q);case qp:return ewQ(A,B,Q);case _R0:return tgA(A,B,Q);case NR0:return Q6Q(A,B,Q);case jR0:return w6Q(A,B,Q);case PR0:return $6Q(A,B,Q);case MR0:return Z6Q(A,B,Q);case sgA: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 B6Q(A,Q);case 26:return X6Q(A,Q);case 27:return Y6Q(A,Q)}}throw Error(`Unsupported or not well formed at ${Q}`)}function f6Q(A){if(A===!0)return 245;else if(A===!1)return 244;else if(A===null)return 246;return 247}function H6Q(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 W6Q(A){if(typeof A=="number"){if(Number.isSafeInteger(A))if(A<0)return OD(qp,Math.abs(A));else return OD(j$0,A);return[H6Q(A)]}else if(A<0n)return OD(qp,A*-1n);else return OD(j$0,A)}var K6Q=new TextEncoder;function U6Q(A,Q){Q.push(...OD(NR0,A.length)),Q.push(K6Q.encode(A))}function G6Q(A,Q){Q.push(...OD(_R0,A.length)),Q.push(A)}function D6Q(A,Q){Q.push(...OD(jR0,A.length));for(let w of A)zp(w,Q)}function q6Q(A,Q){Q.push(new Uint8Array(OD(PR0,A.size)));for(let[w,$]of A.entries())zp(w,Q),zp($,Q)}function z6Q(A,Q){Q.push(...OD(MR0,A.tag)),zp(A.value,Q)}function zp(A,Q){if(typeof A=="boolean"||A===null||A==null){Q.push(f6Q(A));return}if(typeof A=="number"||typeof A=="bigint"){Q.push(...W6Q(A));return}if(typeof A=="string"){U6Q(A,Q);return}if(A instanceof Uint8Array){G6Q(A,Q);return}if(Array.isArray(A)){D6Q(A,Q);return}if(A instanceof Map){q6Q(A,Q);return}if(A instanceof M$0){z6Q(A,Q);return}throw Error("Not implemented")}function OR0(A,Q){if(A.byteLength===0||A.byteLength<=Q||Q<0)throw Error("No data");if(A instanceof Uint8Array)return _N(new DataView(A.buffer),Q);else if(A instanceof ArrayBuffer)return _N(new DataView(A),Q);return _N(A,Q)}function xR0(A){let Q=[];zp(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 J6Q(A){let Q=new Uint8Array(A),w=OR0(Q,0),[$]=w;return $}function F6Q(A){return xR0(A)}var RD={};v6(RD,{verify:()=>CuA,getRandomValues:()=>$EA,digest:()=>wEA});function egA(A){let Q=A.get(hQ.kty);return RR0(Q)&&Q===kf.OKP}function VI(A){let Q=A.get(hQ.kty);return RR0(Q)&&Q===kf.EC2}function Uh(A){let Q=A.get(hQ.kty);return RR0(Q)&&Q===kf.RSA}var hQ;(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"})(hQ||(hQ={}));var kf;(function(A){A[A.OKP=1]="OKP",A[A.EC2=2]="EC2",A[A.RSA=3]="RSA"})(kf||(kf={}));function RR0(A){return Object.values(kf).indexOf(A)>=0}var a4;(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"})(a4||(a4={}));function AEA(A){return Object.values(a4).indexOf(A)>=0}var Dw;(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"})(Dw||(Dw={}));function xD(A){return Object.values(Dw).indexOf(A)>=0}function JI(A){if([Dw.RS1].indexOf(A)>=0)return"SHA-1";else if([Dw.ES256,Dw.PS256,Dw.RS256].indexOf(A)>=0)return"SHA-256";else if([Dw.ES384,Dw.PS384,Dw.RS384].indexOf(A)>=0)return"SHA-384";else if([Dw.ES512,Dw.PS512,Dw.RS512,Dw.EdDSA].indexOf(A)>=0)return"SHA-512";throw Error(`Could not map COSE alg value of ${A} to a WebCrypto alg`)}var Vp=void 0;function jW(){return new Promise((Q,w)=>{if(Vp)return Q(Vp);let $=b6Q.stubThisGlobalThisCrypto();if($)return Vp=$,Q(Vp);return w(new QEA)})}class QEA extends Error{constructor(){super("An instance of the Crypto API could not be located");this.name="MissingWebCrypto"}}var b6Q={stubThisGlobalThisCrypto:()=>globalThis.crypto,setCachedCrypto:(A)=>{Vp=A}};async function wEA(A,Q){let w=await jW(),$=JI(Q),B=await w.subtle.digest($,A);return new Uint8Array(B)}async function $EA(A){return(await jW()).getRandomValues(A),A}async function Gh(A){let Q=await jW(),{keyData:w,algorithm:$}=A;return Q.subtle.importKey("jwk",w,$,!1,["verify"])}async function O$0(A){let{cosePublicKey:Q,signature:w,data:$,shaHashOverride:B}=A,X=await jW(),Y=Q.get(hQ.alg),Z=Q.get(hQ.crv),H=Q.get(hQ.x),W=Q.get(hQ.y);if(!Y)throw Error("Public key was missing alg (EC2)");if(!Z)throw Error("Public key was missing crv (EC2)");if(!H)throw Error("Public key was missing x (EC2)");if(!W)throw Error("Public key was missing y (EC2)");let K;if(Z===a4.P256)K="P-256";else if(Z===a4.P384)K="P-384";else if(Z===a4.P521)K="P-521";else throw Error(`Unexpected COSE crv value of ${Z} (EC2)`);let U={kty:"EC",crv:K,x:uQ.fromBuffer(H),y:uQ.fromBuffer(W),ext:!1},q=await Gh({keyData:U,algorithm:{name:"ECDSA",namedCurve:K}}),V=JI(Y);if(B)V=JI(B);let J={name:"ECDSA",hash:{name:V}};return X.subtle.verify(J,q,w,$)}function vR0(A){if([Dw.EdDSA].indexOf(A)>=0)return"Ed25519";else if([Dw.ES256,Dw.ES384,Dw.ES512,Dw.ES256K].indexOf(A)>=0)return"ECDSA";else if([Dw.RS256,Dw.RS384,Dw.RS512,Dw.RS1].indexOf(A)>=0)return"RSASSA-PKCS1-v1_5";else if([Dw.PS256,Dw.PS384,Dw.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 x$0(A){let{cosePublicKey:Q,signature:w,data:$,shaHashOverride:B}=A,X=await jW(),Y=Q.get(hQ.alg),Z=Q.get(hQ.n),H=Q.get(hQ.e);if(!Y)throw Error("Public key was missing alg (RSA)");if(!xD(Y))throw Error(`Public key had invalid alg ${Y} (RSA)`);if(!Z)throw Error("Public key was missing n (RSA)");if(!H)throw Error("Public key was missing e (RSA)");let W={kty:"RSA",alg:"",n:uQ.fromBuffer(Z),e:uQ.fromBuffer(H),ext:!1},K={name:vR0(Y),hash:{name:JI(Y)}},U={name:vR0(Y)};if(B)K.hash.name=JI(B);if(K.name==="RSASSA-PKCS1-v1_5"){if(K.hash.name==="SHA-256")W.alg="RS256";else if(K.hash.name==="SHA-384")W.alg="RS384";else if(K.hash.name==="SHA-512")W.alg="RS512";else if(K.hash.name==="SHA-1")W.alg="RS1"}else if(K.name==="RSA-PSS"){let q=0;if(K.hash.name==="SHA-256")W.alg="PS256",q=32;else if(K.hash.name==="SHA-384")W.alg="PS384",q=48;else if(K.hash.name==="SHA-512")W.alg="PS512",q=64;U.saltLength=q}else throw Error(`Unexpected RSA key algorithm ${Y} (${K.name})`);let G=await Gh({keyData:W,algorithm:K});return X.subtle.verify(U,G,w,$)}function R$0(A){let Q=p2.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 o5(A){let Q;if(typeof A==="string")if(uQ.isBase64URL(A))Q=uQ.toBase64(A);else if(uQ.isBase64(A))Q=A;else throw Error("Certificate is not a valid base64 or base64url string");else Q=uQ.fromBuffer(A,"base64");let w="";for(let $=0;$<Math.ceil(Q.length/64);$+=1){let B=64*$;w+=`${Q.substr(B,64)}
|
|
1723
1723
|
`}return w=`-----BEGIN CERTIFICATE-----
|
|
@@ -2289,14 +2289,14 @@ ${k}`)}if($!==void 0&&X?.algorithms!==void 0){let F=X.algorithms.map((k)=>k.alg)
|
|
|
2289
2289
|
</form>
|
|
2290
2290
|
</main>
|
|
2291
2291
|
</body>
|
|
2292
|
-
</html>`}function Qd(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(nC0(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function dD(A){return A.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""")}import{randomUUID as rBQ}from"crypto";function ncA(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function nBQ(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,H=Q.slice(Z,Z+Y);return new Uint8Array([...rcA(X),...rcA(H)])}function rcA(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 oC0(A,Q){let w={typ:"JWT",alg:"ES256",kid:A.kid},$=`${ncA(w)}.${ncA(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(nBQ(X)).toString("base64url")}`}var oBQ=600;class sC0{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 Qd(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 xC(dcA(w.params,$))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return Qd(A);let w=await A.formData(),$=await this.validateAuthorizationRequest(new URLSearchParams(lC0(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_${rBQ()}`;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)+oBQ}),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 H=await this.clientStore.getClient(w);if(!H)return{success:!1,error:"Unknown client_id"};if(!LR0(H.redirect_uris,$))return{success:!1,error:"Unregistered redirect_uri"};let W=Y??H.scope;return{success:!0,params:{clientId:w,redirectUri:$,codeChallenge:B,...W?{scope:W}:{},...Z?{state:Z}:{},clientName:H.client_name??H.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return FB("invalid_client_metadata","Request body must be JSON")}try{let w=await this.clientStore.registerClient(Q);return vf(w,201)}catch(w){if(w instanceof Dp)return FB("invalid_client_metadata",w.message);throw w}}async handleTokenRequest(A,Q){let w=await cC0(A),$=w.get("grant_type"),B=iC0(A,w),X=B.clientId??w.get("client_id");if(B.error)return FB("invalid_client",B.error);if(!X)return FB("invalid_request","client_id is required");let Y=await this.clientStore.getClient(X),Z=pC0(Y,B);if(Z)return FB("invalid_client",Z);if($==="authorization_code")return this.handleAuthorizationCodeGrant(w,X,Q);if($==="refresh_token")return this.handleRefreshTokenGrant(w,X,Q);return FB("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 FB("invalid_request","code, redirect_uri, and code_verifier are required");let Y=await this.clientStore.getClient(Q);if(!Y||!LR0(Y.redirect_uris,B))return FB("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 IU)return FB("invalid_grant",Z.message);throw Z}}async handleRefreshTokenGrant(A,Q,w){let $=A.get("refresh_token");if(!$)return FB("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 wV)return FB("invalid_grant",B.message);throw B}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),w=900,$=await oC0(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 vf({access_token:$,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:B})}async handleRevokeRequest(A){let Q=await cC0(A),w=iC0(A,Q),$=w.clientId??Q.get("client_id")??void 0,B=Q.get("token");if(w.error)return FB("invalid_client",w.error);if(!B)return FB("invalid_request","token is required");if($){let X=await this.clientStore.getClient($),Y=pC0(X,w);if(Y)return FB("invalid_client",Y)}return await this.refreshTokenStore.revokeToken(B,$),new Response(null,{status:200})}}class aC0{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 FB("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return FB("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(WB0(A));return vf(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return FB("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return FB("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),WB0(A));if(!Q.verified)return FB("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:ai(A)});return vf({verified:!0},200,{"Set-Cookie":w.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return FB("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(WB0(A));return vf(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),WB0(A));if(!Q.verified)return FB("access_denied","Passkey authentication failed");let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:ai(A)});return vf({verified:!0},200,{"Set-Cookie":w.cookie})}}function WB0(A){let Q=dI(A),w=new URL(Q);return{origin:w.origin,rpID:w.hostname}}import{randomUUID as sBQ}from"crypto";var wd=86400;class tC0{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??wd}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_${sBQ()}`,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 RU(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:RU(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:LC0(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 xC(pcA(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupStateStore.recordDelivery(A,Q,w)}}class KB0{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=xU(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>xU(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??iI(this.issuer),this.keyStore=new N$0({storageDir:A.storageDir}),this.a2aKeyStore=new kR0({storageDir:A.storageDir}),this.clientStore=new _$0({storageDir:A.storageDir}),this.authCodeStore=new k$0({storageDir:A.storageDir}),this.sessionStore=new XB0({storageDir:A.storageDir}),this.peerTrustStore=new QB0({storageDir:A.storageDir}),this.passkeyService=new AB0({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new tC0({setupStateStore:new kC0({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??wd}),this.oauthEndpoints=new sC0({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new wB0({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new aC0({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(iI(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:RU(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=xU(A);return{issuer:Q,authorization_endpoint:RU(Q,"/authorize"),token_endpoint:RU(Q,"/token"),registration_endpoint:RU(Q,"/register"),revocation_endpoint:RU(Q,"/revoke"),jwks_uri:RU(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:[xU(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 Qd(A)}async verifyBearerToken(A,Q={}){let w=uC0(A);if(!w)return;let $=Q.issuer?xU(Q.issuer):this.resolveRequestIssuer(A);return mC0(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"&&ucA(w))return ccA();if(A.method==="GET"){if(w==="/.well-known/oauth-authorization-server")return sI(vf(this.getAuthorizationServerMetadata(Q)));if(w==="/.well-known/jwks.json")return sI(vf(await this.getJwks()));if(w==="/.well-known/oauth-protected-resource")return sI(vf(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 sI(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&w==="/token")return sI(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&w==="/revoke")return sI(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=dI(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&iI(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=dC0(new URL(A.url).searchParams.get("return_to"));return xC(nC0(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=dC0(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":NC0(ai(A)),"Cache-Control":"no-store"}})}}C0();var UB0="email:send",ocA=f.strictObject({to:f.string().email(),subject:f.string().min(1),text:f.string().min(1),html:f.string().min(1).optional(),sensitivity:f.enum(["normal","secret"]).default("normal")});fA();C0();var scA={name:"@brains/notifications",version:"0.2.0-alpha.168",description:"Generic notification routing for transactional and administrative messages",dependencies:{"@brains/email-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var eC0="notifications:send",tBQ=f.looseObject({}),eBQ=f.discriminatedUnion("type",[f.strictObject({type:f.literal("email"),address:f.email()})]),A5Q=f.strictObject({recipient:eBQ,title:f.string().min(1),body:f.string().min(1),html:f.string().min(1).optional(),sensitivity:f.enum(["normal","secret"]).default("normal")}),acA=f.discriminatedUnion("status",[f.strictObject({status:f.literal("sent"),deliveryId:f.string().optional()}),f.strictObject({status:f.literal("failed")})]);class tcA extends Uw{constructor(A={}){super("notifications",scA,A,tBQ)}async onRegister(A){A.messaging.subscribe(eC0,async(Q)=>{let w=A5Q.parse(Q.payload),$={to:w.recipient.address,subject:w.title,text:w.body,...w.html?{html:w.html}:{},sensitivity:w.sensitivity},B=await A.messaging.send({type:UB0,payload:$});if(!("success"in B)||!B.success||!B.data)return{success:!1,error:"Notification delivery failed"};let X=B.data;if(X.status!=="sent")return{success:!1,error:"Notification delivery failed"};return{success:!0,data:X.id?{status:"sent",deliveryId:X.id}:{status:"sent"}}})}}function GB0(A={}){return new tcA(A)}fA();C0();var ecA={name:"@brains/auth-service",version:"0.2.0-alpha.168",description:"Embedded OAuth/OIDC auth service for brain operator authentication",dependencies:{"@brains/notifications":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@simplewebauthn/server":"^13.3.1",jose:"^6.2.3"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},files:["src"],main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var w5Q=f.union([f.string().email(),f.object({to:f.string().email(),subject:f.string().min(1),body:f.string().min(1)}).strict()]),$5Q=f.object({issuer:f.string().optional(),trustedIssuers:f.array(f.string()).default([]),allowLocalhostIssuers:f.boolean().optional(),storageDir:f.string().default("./data/auth"),setupTokenTtlSeconds:f.number().int().positive().default(wd),setupEmail:w5Q.optional()}),DB0;function A4(){return DB0}class Ay0 extends Uw{service;constructor(A={}){super("auth-service",ecA,A,$5Q)}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 KB0({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(),DB0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(DB0===this.service)DB0=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 $=B5Q(this.config.setupEmail,w);if(await Q.hasSetupEmailDelivery(w.setupTokenId,$.to))return;let B=await A.messaging.send({type:eC0,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=acA.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 B5Q(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(`
|
|
2293
|
-
`)}}return{to:A.to,subject:AlA(A.subject,Q),body:AlA(A.body,Q)}}function AlA(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 $d(A={}){return new Ay0(A)}C0();var Qy0=f.object({transport:f.enum(["stdio","http"]).default("http"),mode:f.enum(["basic","debug"]).default("basic"),httpPort:f.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:f.string().describe("Bearer token for HTTP transport authentication").optional(),sessionIdleTtlMs:f.number().describe("Idle time in ms after which an HTTP session is closed and evicted").default(1800000)});C0();import{createHash as f5Q,randomUUID as H5Q}from"crypto";function X5Q(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function Bd(A,Q){let w=A?.[Q];return typeof w==="string"&&w.length>0?w:void 0}function Y5Q(A){let Q=X5Q(A.data)?A.data:void 0,w=A.args,$=Bd(Q,"entityId")??Bd(Q,"id"),B=A.jobId??Bd(Q,"jobId"),X=Bd(w,"entityType")??Bd(w,"type");if(!$&&!B)return;return{toolName:A.toolName,...X?{entityType:X}:{},...$?{entityId:$}:{},...B?{jobId:B}:{}}}function Z5Q(A){return A?.map(Y5Q).filter((Q)=>Q!==void 0)??[]}function wy0(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 $=Z5Q(A.toolResults);return{success:!0,data:{text:A.text,...Q.conversationId?{conversationId:Q.conversationId}:{},...A.toolResults?{toolResults:A.toolResults}:{},...$.length>0?{readYourWrites:$}:{}}}}var QlA=f.object({message:f.string().min(1),conversationId:f.string().min(1).optional().describe("Opaque conversation handle returned by a previous chat call. Omit it to start a new isolated conversation.")}),wlA=f.object({approvalId:f.string().min(1),confirmed:f.boolean(),conversationId:f.string().min(1).describe("Exact conversation handle returned by the chat confirmation.")});function $lA(A,Q,w,$){let B=A.conversationId??w??$??`conversation-${H5Q()}`,X=f5Q("sha256").update(Q).digest("hex").slice(0,16);return{handle:B,internalId:`mcp:${X}:${B}`}}function BlA(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 XlA(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:QlA.shape,visibility:"public",sideEffects:"writes",handler:async(w,$)=>{let B=QlA.parse(w),X=Q();if(!X)return{success:!1,error:"MCP chat tool is not initialized."};let Y=$lA(B,$.userId,$.conversationId,$.channelId),Z=await X.agent.chat(B.message,Y.internalId,{...BlA($)});return wy0(Z,{conversationId:Y.handle})}},{name:"confirm",description:"Resolve a pending confirmation returned by chat. Use this only after chat returns needsConfirmation with an approvalId.",inputSchema:wlA.shape,visibility:"public",sideEffects:"writes",handler:async(w,$)=>{let B=wlA.parse(w),X=Q();if(!X)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=$lA(B,$.userId,$.conversationId,$.channelId),Z=await X.agent.confirmPendingAction(Y.internalId,B.confirmed,B.approvalId,BlA($));return wy0(Z,{conversationId:Y.handle})}}]}fA();function $y0(A,Q){A.messaging.subscribe("job-progress",async(w)=>{let $=cx.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 YlA={name:"@brains/mcp",version:"0.2.0-alpha.
|
|
2292
|
+
</html>`}function Qd(A){let Q=`${new URL(A.url).pathname}${new URL(A.url).search}`;return new Response(nC0(Q,"Operator login required"),{status:401,headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}function dD(A){return A.replaceAll("&","&").replaceAll("<","<").replaceAll(">",">").replaceAll('"',""")}import{randomUUID as rBQ}from"crypto";function ncA(A){return Buffer.from(JSON.stringify(A)).toString("base64url")}function nBQ(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,H=Q.slice(Z,Z+Y);return new Uint8Array([...rcA(X),...rcA(H)])}function rcA(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 oC0(A,Q){let w={typ:"JWT",alg:"ES256",kid:A.kid},$=`${ncA(w)}.${ncA(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(nBQ(X)).toString("base64url")}`}var oBQ=600;class sC0{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 Qd(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 xC(dcA(w.params,$))}async handleAuthorizeApproval(A){let Q=await this.sessionStore.getSessionFromRequest(A);if(!Q)return Qd(A);let w=await A.formData(),$=await this.validateAuthorizationRequest(new URLSearchParams(lC0(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_${rBQ()}`;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)+oBQ}),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 H=await this.clientStore.getClient(w);if(!H)return{success:!1,error:"Unknown client_id"};if(!LR0(H.redirect_uris,$))return{success:!1,error:"Unregistered redirect_uri"};let W=Y??H.scope;return{success:!0,params:{clientId:w,redirectUri:$,codeChallenge:B,...W?{scope:W}:{},...Z?{state:Z}:{},clientName:H.client_name??H.client_id}}}async handleClientRegistration(A){let Q;try{Q=await A.json()}catch{return FB("invalid_client_metadata","Request body must be JSON")}try{let w=await this.clientStore.registerClient(Q);return vf(w,201)}catch(w){if(w instanceof Dp)return FB("invalid_client_metadata",w.message);throw w}}async handleTokenRequest(A,Q){let w=await cC0(A),$=w.get("grant_type"),B=iC0(A,w),X=B.clientId??w.get("client_id");if(B.error)return FB("invalid_client",B.error);if(!X)return FB("invalid_request","client_id is required");let Y=await this.clientStore.getClient(X),Z=pC0(Y,B);if(Z)return FB("invalid_client",Z);if($==="authorization_code")return this.handleAuthorizationCodeGrant(w,X,Q);if($==="refresh_token")return this.handleRefreshTokenGrant(w,X,Q);return FB("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 FB("invalid_request","code, redirect_uri, and code_verifier are required");let Y=await this.clientStore.getClient(Q);if(!Y||!LR0(Y.redirect_uris,B))return FB("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 IU)return FB("invalid_grant",Z.message);throw Z}}async handleRefreshTokenGrant(A,Q,w){let $=A.get("refresh_token");if(!$)return FB("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 wV)return FB("invalid_grant",B.message);throw B}}async createTokenResponse(A){let Q=Math.floor(Date.now()/1000),w=900,$=await oC0(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 vf({access_token:$,token_type:"Bearer",expires_in:900,...A.scope?{scope:A.scope}:{},refresh_token:B})}async handleRevokeRequest(A){let Q=await cC0(A),w=iC0(A,Q),$=w.clientId??Q.get("client_id")??void 0,B=Q.get("token");if(w.error)return FB("invalid_client",w.error);if(!B)return FB("invalid_request","token is required");if($){let X=await this.clientStore.getClient($),Y=pC0(X,w);if(Y)return FB("invalid_client",Y)}return await this.refreshTokenStore.revokeToken(B,$),new Response(null,{status:200})}}class aC0{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 FB("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return FB("access_denied","Invalid setup token");let Q=await this.passkeyService.generateRegistrationOptions(WB0(A));return vf(Q)}async handleRegistrationVerify(A){if(await this.passkeyService.hasCredentials())return FB("access_denied","Passkey setup already completed");if(!this.setupFlow.hasValidSetupToken(A))return FB("access_denied","Invalid setup token");let Q=await this.passkeyService.verifyRegistrationResponse(await A.json(),WB0(A));if(!Q.verified)return FB("access_denied","Passkey registration failed");await this.setupFlow.clearSetupState();let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:ai(A)});return vf({verified:!0},200,{"Set-Cookie":w.cookie})}async handleAuthenticationOptions(A){if(!await this.passkeyService.hasCredentials())return FB("access_denied","No passkey registered");let Q=await this.passkeyService.generateAuthenticationOptions(WB0(A));return vf(Q)}async handleAuthenticationVerify(A){let Q=await this.passkeyService.verifyAuthenticationResponse(await A.json(),WB0(A));if(!Q.verified)return FB("access_denied","Passkey authentication failed");let w=await this.sessionStore.createSession(Q.subject??"single-operator",{secure:ai(A)});return vf({verified:!0},200,{"Set-Cookie":w.cookie})}}function WB0(A){let Q=dI(A),w=new URL(Q);return{origin:w.origin,rpID:w.hostname}}import{randomUUID as sBQ}from"crypto";var wd=86400;class tC0{setupStateStore;passkeyService;setupTokenTtlSeconds;setupToken;constructor(A){this.setupStateStore=A.setupStateStore,this.passkeyService=A.passkeyService,this.setupTokenTtlSeconds=A.setupTokenTtlSeconds??wd}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_${sBQ()}`,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 RU(A,`/setup?token=${encodeURIComponent(Q.token)}`)}async getOperatorSetupRequired(A){if(await this.passkeyService.hasCredentials())return;let Q=this.getValidSetupToken();if(!Q)return;return{setupUrl:RU(A,`/setup?token=${encodeURIComponent(Q.token)}`),expiresAt:Q.expiresAt,setupTokenId:LC0(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 xC(pcA(Q))}async hasSetupEmailDelivery(A,Q){return this.setupStateStore.hasDelivery(A,Q)}async recordSetupEmailDelivery(A,Q,w={}){await this.setupStateStore.recordDelivery(A,Q,w)}}class KB0{issuer;trustedIssuers;allowLocalhostIssuers;keyStore;a2aKeyStore;clientStore;authCodeStore;sessionStore;peerTrustStore;passkeyService;setupFlow;oauthEndpoints;webauthnEndpoints;logger;constructor(A){this.issuer=xU(A.issuer),this.trustedIssuers=new Set([this.issuer,...(A.trustedIssuers??[]).map((Q)=>xU(Q))]),this.allowLocalhostIssuers=A.allowLocalhostIssuers??iI(this.issuer),this.keyStore=new N$0({storageDir:A.storageDir}),this.a2aKeyStore=new kR0({storageDir:A.storageDir}),this.clientStore=new _$0({storageDir:A.storageDir}),this.authCodeStore=new k$0({storageDir:A.storageDir}),this.sessionStore=new XB0({storageDir:A.storageDir}),this.peerTrustStore=new QB0({storageDir:A.storageDir}),this.passkeyService=new AB0({storageDir:A.storageDir,...A.logger?{logger:A.logger}:{}}),this.setupFlow=new tC0({setupStateStore:new kC0({storageDir:A.storageDir}),passkeyService:this.passkeyService,setupTokenTtlSeconds:A.setupTokenTtlSeconds??wd}),this.oauthEndpoints=new sC0({clientStore:this.clientStore,authCodeStore:this.authCodeStore,refreshTokenStore:new wB0({storageDir:A.storageDir}),sessionStore:this.sessionStore,keyStore:this.keyStore}),this.webauthnEndpoints=new aC0({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(iI(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:RU(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=xU(A);return{issuer:Q,authorization_endpoint:RU(Q,"/authorize"),token_endpoint:RU(Q,"/token"),registration_endpoint:RU(Q,"/register"),revocation_endpoint:RU(Q,"/revoke"),jwks_uri:RU(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:[xU(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 Qd(A)}async verifyBearerToken(A,Q={}){let w=uC0(A);if(!w)return;let $=Q.issuer?xU(Q.issuer):this.resolveRequestIssuer(A);return mC0(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"&&ucA(w))return ccA();if(A.method==="GET"){if(w==="/.well-known/oauth-authorization-server")return sI(vf(this.getAuthorizationServerMetadata(Q)));if(w==="/.well-known/jwks.json")return sI(vf(await this.getJwks()));if(w==="/.well-known/oauth-protected-resource")return sI(vf(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 sI(await this.oauthEndpoints.handleClientRegistration(A));if(A.method==="POST"&&w==="/token")return sI(await this.oauthEndpoints.handleTokenRequest(A,Q));if(A.method==="POST"&&w==="/revoke")return sI(await this.oauthEndpoints.handleRevokeRequest(A));return new Response("Not Found",{status:404})}async handleWellKnownRequest(A){return this.handleRequest(A)}resolveRequestIssuer(A){let Q=dI(A,this.issuer);if(this.trustedIssuers.has(Q)||this.allowLocalhostIssuers&&iI(Q))return Q;throw Error(`Request issuer ${Q} is not in trusted issuers`)}handleLoginPage(A){let Q=dC0(new URL(A.url).searchParams.get("return_to"));return xC(nC0(Q))}async handleLogout(A){await this.sessionStore.revokeSessionFromRequest(A);let Q=dC0(new URL(A.url).searchParams.get("return_to"));return new Response(null,{status:302,headers:{Location:Q,"Set-Cookie":NC0(ai(A)),"Cache-Control":"no-store"}})}}C0();var UB0="email:send",ocA=f.strictObject({to:f.string().email(),subject:f.string().min(1),text:f.string().min(1),html:f.string().min(1).optional(),sensitivity:f.enum(["normal","secret"]).default("normal")});fA();C0();var scA={name:"@brains/notifications",version:"0.2.0-alpha.169",description:"Generic notification routing for transactional and administrative messages",dependencies:{"@brains/email-contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module"};var eC0="notifications:send",tBQ=f.looseObject({}),eBQ=f.discriminatedUnion("type",[f.strictObject({type:f.literal("email"),address:f.email()})]),A5Q=f.strictObject({recipient:eBQ,title:f.string().min(1),body:f.string().min(1),html:f.string().min(1).optional(),sensitivity:f.enum(["normal","secret"]).default("normal")}),acA=f.discriminatedUnion("status",[f.strictObject({status:f.literal("sent"),deliveryId:f.string().optional()}),f.strictObject({status:f.literal("failed")})]);class tcA extends Uw{constructor(A={}){super("notifications",scA,A,tBQ)}async onRegister(A){A.messaging.subscribe(eC0,async(Q)=>{let w=A5Q.parse(Q.payload),$={to:w.recipient.address,subject:w.title,text:w.body,...w.html?{html:w.html}:{},sensitivity:w.sensitivity},B=await A.messaging.send({type:UB0,payload:$});if(!("success"in B)||!B.success||!B.data)return{success:!1,error:"Notification delivery failed"};let X=B.data;if(X.status!=="sent")return{success:!1,error:"Notification delivery failed"};return{success:!0,data:X.id?{status:"sent",deliveryId:X.id}:{status:"sent"}}})}}function GB0(A={}){return new tcA(A)}fA();C0();var ecA={name:"@brains/auth-service",version:"0.2.0-alpha.169",description:"Embedded OAuth/OIDC auth service for brain operator authentication",dependencies:{"@brains/notifications":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@simplewebauthn/server":"^13.3.1",jose:"^6.2.3"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/node":"^20.19.43",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},files:["src"],main:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var w5Q=f.union([f.string().email(),f.object({to:f.string().email(),subject:f.string().min(1),body:f.string().min(1)}).strict()]),$5Q=f.object({issuer:f.string().optional(),trustedIssuers:f.array(f.string()).default([]),allowLocalhostIssuers:f.boolean().optional(),storageDir:f.string().default("./data/auth"),setupTokenTtlSeconds:f.number().int().positive().default(wd),setupEmail:w5Q.optional()}),DB0;function A4(){return DB0}class Ay0 extends Uw{service;constructor(A={}){super("auth-service",ecA,A,$5Q)}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 KB0({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(),DB0=this.service}async onReady(A){await this.requestSetupEmailIfNeeded(A)}async onShutdown(){if(DB0===this.service)DB0=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 $=B5Q(this.config.setupEmail,w);if(await Q.hasSetupEmailDelivery(w.setupTokenId,$.to))return;let B=await A.messaging.send({type:eC0,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=acA.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 B5Q(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(`
|
|
2293
|
+
`)}}return{to:A.to,subject:AlA(A.subject,Q),body:AlA(A.body,Q)}}function AlA(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 $d(A={}){return new Ay0(A)}C0();var Qy0=f.object({transport:f.enum(["stdio","http"]).default("http"),mode:f.enum(["basic","debug"]).default("basic"),httpPort:f.number().describe("Port for HTTP transport (only used when transport is 'http')").default(3333),authToken:f.string().describe("Bearer token for HTTP transport authentication").optional(),sessionIdleTtlMs:f.number().describe("Idle time in ms after which an HTTP session is closed and evicted").default(1800000)});C0();import{createHash as f5Q,randomUUID as H5Q}from"crypto";function X5Q(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}function Bd(A,Q){let w=A?.[Q];return typeof w==="string"&&w.length>0?w:void 0}function Y5Q(A){let Q=X5Q(A.data)?A.data:void 0,w=A.args,$=Bd(Q,"entityId")??Bd(Q,"id"),B=A.jobId??Bd(Q,"jobId"),X=Bd(w,"entityType")??Bd(w,"type");if(!$&&!B)return;return{toolName:A.toolName,...X?{entityType:X}:{},...$?{entityId:$}:{},...B?{jobId:B}:{}}}function Z5Q(A){return A?.map(Y5Q).filter((Q)=>Q!==void 0)??[]}function wy0(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 $=Z5Q(A.toolResults);return{success:!0,data:{text:A.text,...Q.conversationId?{conversationId:Q.conversationId}:{},...A.toolResults?{toolResults:A.toolResults}:{},...$.length>0?{readYourWrites:$}:{}}}}var QlA=f.object({message:f.string().min(1),conversationId:f.string().min(1).optional().describe("Opaque conversation handle returned by a previous chat call. Omit it to start a new isolated conversation.")}),wlA=f.object({approvalId:f.string().min(1),confirmed:f.boolean(),conversationId:f.string().min(1).describe("Exact conversation handle returned by the chat confirmation.")});function $lA(A,Q,w,$){let B=A.conversationId??w??$??`conversation-${H5Q()}`,X=f5Q("sha256").update(Q).digest("hex").slice(0,16);return{handle:B,internalId:`mcp:${X}:${B}`}}function BlA(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 XlA(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:QlA.shape,visibility:"public",sideEffects:"writes",handler:async(w,$)=>{let B=QlA.parse(w),X=Q();if(!X)return{success:!1,error:"MCP chat tool is not initialized."};let Y=$lA(B,$.userId,$.conversationId,$.channelId),Z=await X.agent.chat(B.message,Y.internalId,{...BlA($)});return wy0(Z,{conversationId:Y.handle})}},{name:"confirm",description:"Resolve a pending confirmation returned by chat. Use this only after chat returns needsConfirmation with an approvalId.",inputSchema:wlA.shape,visibility:"public",sideEffects:"writes",handler:async(w,$)=>{let B=wlA.parse(w),X=Q();if(!X)return{success:!1,error:"MCP confirm tool is not initialized."};let Y=$lA(B,$.userId,$.conversationId,$.channelId),Z=await X.agent.confirmPendingAction(Y.internalId,B.confirmed,B.approvalId,BlA($));return wy0(Z,{conversationId:Y.handle})}}]}fA();function $y0(A,Q){A.messaging.subscribe("job-progress",async(w)=>{let $=cx.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 YlA={name:"@brains/mcp",version:"0.2.0-alpha.169",dependencies:{"@brains/auth-service":"workspace:*","@brains/mcp-service":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@modelcontextprotocol/sdk":"^1.29.0",cors:"^2.8.5",express:"^4.18.0","express-async-handler":"^1.2.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/cors":"^2.8.17",typescript:"^7.0.2"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};class aI extends UD{mcpTransport;stdioServer;httpServer;domain;constructor(A={}){let Q={...A,authToken:A.authToken??process.env.MCP_AUTH_TOKEN};super("mcp",YlA,Q,Qy0)}async getTools(){return XlA(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"});$y0(A,this.logger)}getOrCreateHttpServer(){if(this.httpServer)return this.httpServer;let A=A4();return this.httpServer=v3.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),$=A4(),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=FU.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(){FU.resetInstance(),v3.resetInstance()}}fA();function Xd(A,Q=2000){if(A.length<=Q)return[A];let w=G5Q(A),$=[],B="";for(let X of w){let Y=B?`
|
|
2294
2294
|
|
|
2295
2295
|
`:"";if(B.length+Y.length+X.length<=Q){B+=Y+X;continue}if(B)$.push(B),B="";if(X.length<=Q){B=X;continue}K5Q(X,Q,$,(Z)=>{B=Z})}if(B)$.push(B);return $}function K5Q(A,Q,w,$){let B="",X=A.split(`
|
|
2296
2296
|
`);for(let Y of X){let Z=B?`
|
|
2297
2297
|
`:"";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}U5Q(Y,Q,w,(H)=>{B=H})}$(B)}function U5Q(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 H=0;H<Y.length;H+=Q){let W=Y.slice(H,H+Q);if(H+Q>=Y.length)B=W;else w.push(W)}else B=Y}$(B)}function G5Q(A){let Q=[],w=A.split(`
|
|
2298
2298
|
`),$="",B=!1;for(let X of w){if(X.startsWith("```"))B=!B;if(!B&&X===""&&$){Q.push($),$="";continue}$+=($?`
|
|
2299
|
-
`:"")+X}if($)Q.push($);return Q}k2();var uf=D1(Fc0(),1);fA();C0();var Ic0=f.object({botToken:f.string().min(1).describe("Discord bot token"),allowedChannels:f.array(f.string()).default([]),requireMention:f.boolean().default(!0),allowDMs:f.boolean().default(!0),showTypingIndicator:f.boolean().default(!0),statusMessage:f.string().default("Mention me to chat"),useThreads:f.boolean().default(!0),threadAutoArchive:f.union([f.literal(60),f.literal(1440),f.literal(4320),f.literal(10080)]).default(1440),...Su.shape,captureUrlEmoji:f.string().default("\uD83D\uDD16")});var JL1={name:"@brains/discord",version:"0.2.0-alpha.
|
|
2299
|
+
`:"")+X}if($)Q.push($);return Q}k2();var uf=D1(Fc0(),1);fA();C0();var Ic0=f.object({botToken:f.string().min(1).describe("Discord bot token"),allowedChannels:f.array(f.string()).default([]),requireMention:f.boolean().default(!0),allowDMs:f.boolean().default(!0),showTypingIndicator:f.boolean().default(!0),statusMessage:f.string().default("Mention me to chat"),useThreads:f.boolean().default(!0),threadAutoArchive:f.union([f.literal(60),f.literal(1440),f.literal(4320),f.literal(10080)]).default(1440),...Su.shape,captureUrlEmoji:f.string().default("\uD83D\uDD16")});var JL1={name:"@brains/discord",version:"0.2.0-alpha.169",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 pn=2000,clQ={completed:"Action completed",declined:"Action declined",failed:"Action failed"},llQ={completed:2278750,declined:9741240,failed:15680580},plQ=8388608,ilQ=8000,dlQ=100;function C70(A){return!!A&&typeof A==="object"&&"send"in A&&"sendTyping"in A}class gb extends aK{client=null;fetchText;pendingConfirmations=new Map;typingIntervals=new Map;constructor(A,Q={}){super("discord",JL1,A,Ic0);this.fetchText=Q.fetchText??ZOA}async onRegister(A){await super.onRegister(A),this.client=new uf.Client({intents:[uf.GatewayIntentBits.Guilds,uf.GatewayIntentBits.GuildMessages,uf.GatewayIntentBits.MessageContent,uf.GatewayIntentBits.DirectMessages],partials:[uf.Partials.Channel]}),this.client.on(uf.Events.MessageCreate,(Q)=>{this.handleMessage(Q)}),this.client.on(uf.Events.InteractionCreate,(Q)=>{this.handleInteraction(Q)}),this.client.once(uf.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(!C70(w))return;let $=Xd(Q,pn);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(!C70(w))return;if(typeof Q!=="string")return(await w.send(Q)).id;let $=Xd(Q,pn),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(!C70($))return!1;try{return await(await $.messages.fetch(Q)).edit(w.slice(0,pn)),!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 H=Q||B||!this.config.requireMention||$;if(Y&&(!H||this.willRouteUseNonSpaceConversation(A)))await this.capturePassiveSpaceMessage(A,X).catch((U)=>this.logger.error("Passive Discord space capture failed",{error:U,channelId:X}));if(!H){if(this.config.captureUrls){let U=this.extractCaptureableUrls(A.content,this.config.blockedUrlDomains);if(U.length>0){await A.react(this.config.captureUrlEmoji).catch((G)=>this.logger.debug("React failed",{error:G}));for(let G of U)await this.captureUrlViaAgent(G,A.channel.id,A.author.id,"discord",Z).catch((q)=>this.logger.error("URL capture failed",{error:q,url:G}))}}return}let W=this.stripMention(A.content);if(A.attachments.size>0){let U=this.context.permissions.getUserLevel("discord",A.author.id,Z);if(U==="anchor"||U==="trusted")for(let q of A.attachments.values()){let V=q.name,J=q.contentType??void 0,F=q.size;if(!this.isUploadableTextFile(V,J))continue;if(!this.isFileSizeAllowed(F))continue;try{let k=await this.fetchText(q.url);W+=`
|
|
2300
2300
|
|
|
2301
2301
|
`+this.formatFileUploadMessage(V,k)}catch(k){this.logger.error("Failed to download attachment",{error:k,filename:V})}}}if(W=W.trim(),!W)return;let K=A.channel.id;await this.routeToAgent(W,K,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:lX(A,dlQ),autoArchiveDuration:this.config.threadAutoArchive})).id}catch(W){this.logger.error("Failed to create thread",{error:W})}let Y=`discord-${X}`,Z=this.context.permissions.getUserLevel("discord",w.author.id,$),H=this.getChannelName(w);this.startProcessingInput(X);try{let W=this.client?.channels.cache.get(X);if(C70(W))this.startTypingIndicator(W);if(this.pendingConfirmations.has(Y)){if(await this.handleConfirmationResponse(A,Y,X,w,$))return}let K=await B.chat(A,Y,{userPermissionLevel:Z,interfaceType:"discord",channelId:X,channelName:H,...this.buildUserMessageMetadata(w,Q,H,{threadId:X!==Q||w.channel.isThread()?X:void 0})});await this.handleAgentResponseToolStatuses(K,Y);let U=h_(K.cards);if(U.length>0)this.pendingConfirmations.set(Y,new Set(U.map((q)=>q.id)));else if(K.pendingConfirmations)this.pendingConfirmations.set(Y,new Set(K.pendingConfirmations.map((q)=>q.id)));else this.pendingConfirmations.delete(Y);let G=await this.sendMessageWithId({channelId:X,message:NR(K.text,U),approvalCards:U});if(G&&K.toolResults){for(let q of K.toolResults)if(q.jobId)this.trackAgentResponseForJob(q.jobId,G,X)}}catch(W){this.logger.error("Error handling message",{error:W,channelId:X}),this.sendMessageToChannel({channelId:X,message:`**Error:** ${W instanceof Error?W.message:"Unknown error"}`})}finally{this.endProcessingInput(),this.stopTypingIndicator(X)}}buildApprovalMessagePayload(A,Q){let w=Q.length>1;return{content:lX(A.trim().length>0?`${A}
|
|
2302
2302
|
|
|
@@ -2366,7 +2366,7 @@ ${A.value}
|
|
|
2366
2366
|
`);if(T70(A))return this.renderList(A,0,(Q)=>this.nodeToDiscordMarkdown(Q));if(A.type==="break")return`
|
|
2367
2367
|
`;if(A.type==="thematicBreak")return"---";if(Rl0(A))return`\`\`\`
|
|
2368
2368
|
${vl0(A)}
|
|
2369
|
-
\`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToDiscordMarkdown(Q))}};var Th1={DeferredChannelMessageWithSource:5,DeferredUpdateMessage:6},o70="https://discord.com/api/v10",Sh1=2000,jaQ=/^[0-9a-f]{64}$/,PaQ=/^[0-9a-f]+$/,MaQ=class A{name="discord";userName;botUserId;apiBaseUrl;botToken;publicKey;applicationId;mentionRoleIds;interactionFlags;chat=null;logger;formatConverter=new NaQ;requestContext=new qaQ;threadParentCache=new Map;static THREAD_PARENT_CACHE_TTL=300000;constructor(Q={}){let w=Q.botToken??process.env.DISCORD_BOT_TOKEN;if(!w)throw new rW("discord","botToken is required. Set DISCORD_BOT_TOKEN or provide it in config.");let $=Q.publicKey??process.env.DISCORD_PUBLIC_KEY;if(!$)throw new rW("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 rW("discord","applicationId is required. Set DISCORD_APPLICATION_ID or provide it in config.");if(this.apiBaseUrl=Q.apiUrl??process.env.DISCORD_API_URL??o70,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 i70("info").child("discord"),this.userName=Q.userName??"bot",!jaQ.test(this.publicKey))this.logger.error("Invalid Discord public key format",{length:this.publicKey.length,isHex:PaQ.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 U=JSON.parse(X);return this.handleForwardedGatewayEvent(U,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"),H=Q.headers.get("x-signature-timestamp");if(!await this.verifySignature(B,Z,H))return this.logger.warn("Discord signature verification failed, returning 401"),new Response("Invalid signature",{status:401});this.logger.info("Discord signature verification passed");let K;try{K=JSON.parse(X)}catch{return new Response("Invalid JSON",{status:400})}if(this.logger.info("Discord interaction parsed",{type:K.type,typeIsPing:K.type===iy.Ping,expectedPingType:iy.Ping,id:K.id}),K.type===iy.Ping){let U=JSON.stringify({type:$r.InteractionResponseType.PONG});return this.logger.info("Discord PING received, responding with PONG",{responseBody:U,responseType:$r.InteractionResponseType.PONG}),new Response(U,{status:200,headers:{"Content-Type":"application/json"}})}if(K.type===iy.MessageComponent)return this.handleComponentInteraction(K,w),this.respondToInteraction({type:Th1.DeferredUpdateMessage});if(K.type===iy.ApplicationCommand){let U=this.getApplicationCommandContext(K),G=this.getInteractionFlags(U);return this.handleApplicationCommandInteraction(U,w),this.respondToInteraction({...G===void 0?{}:{data:{flags:G}},type:Th1.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 $r.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 H=Q.channel,W=H?.type===11||H?.type===12,K=W&&H?.parent_id?H.parent_id:X,U=W?this.encodeThreadId({guildId:Y,channelId:K,threadId:X}):this.encodeThreadId({guildId:Y,channelId:X}),G=VaQ($),q={actionId:G.actionId,value:G.value??G.actionId,user:{userId:B.id,userName:B.username,fullName:B.global_name||B.username,isBot:B.bot??!1,isMe:!1},messageId:Z,threadId:U,adapter:this,raw:Q};this.logger.debug("Processing Discord button action",{actionId:$,messageId:Z,threadId:U}),this.chat.processAction(q,w)}getApplicationCommandContext(Q){let w=Q.data?.name;if(!w)return this.logger.warn("No command name in application command interaction"),null;let $=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,H=Z&&Y?.parent_id?Y.parent_id:B,W=Z?this.encodeThreadId({guildId:X,channelId:H,threadId:B}):this.encodeThreadId({guildId:X,channelId:B}),{command:K,text:U}=this.parseSlashCommand(w,Q.data?.options);return{channelId:W,command:K,interaction:Q,text:U,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 q=await(await this.discordFetch(`/channels/${B}`,"GET")).json();if(q.parent_id)X=B,Y=q.parent_id,this.logger.debug("Fetched thread parent for forwarded message",{threadId:B,parentId:q.parent_id})}catch(G){this.logger.error("Failed to fetch thread parent",{error:String(G),channelId:B})}let Z=Q.is_mention||Q.mentions.some((G)=>G.id===this.applicationId),H=this.mentionRoleIds.length>0&&Q.mention_roles?.some((G)=>this.mentionRoleIds.includes(G)),W=Z||H;if(!X&&W)try{let G=await this.createDiscordThread(B,Q.id);X=G.id,this.logger.debug("Created Discord thread for forwarded mention",{channelId:B,messageId:Q.id,threadId:G.id})}catch(G){this.logger.error("Failed to create Discord thread for mention",{error:String(G),messageId:Q.id})}let K=this.encodeThreadId({guildId:$,channelId:Y,threadId:X}),U=new q5({id:Q.id,threadId:K,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.global_name||Q.author.username,isBot:Q.author.bot===!0,isMe:Q.author.id===this.applicationId},metadata:{dateSent:new Date(Q.timestamp),edited:!1},attachments:Q.attachments.map((G)=>({type:this.getAttachmentType(G.content_type),url:G.url,name:G.filename,mimeType:G.content_type,size:G.size})),raw:Q,isMention:W});try{await this.chat.handleIncomingMessage(this,K,U)}catch(G){this.logger.error("Error handling forwarded message",{error:String(G),messageId:Q.id})}}async handleForwardedReaction(Q,w,$){if(!this.chat)return;let B=Q.guild_id||"@me",X=Q.channel_id,Y,Z=X;if(Q.channel_type===YP.GuildPublicThread||Q.channel_type===YP.GuildPrivateThread){let q=this.threadParentCache.get(X);if(q&&q.expiresAt>Date.now())Y=X,Z=q.parentId;else try{let J=await(await this.discordFetch(`/channels/${X}`,"GET")).json();if(J.parent_id)Y=X,Z=J.parent_id,this.threadParentCache.set(X,{parentId:J.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 H=this.encodeThreadId({guildId:B,channelId:Z,threadId:Y}),W=Q.emoji.name||"unknown",K=this.normalizeDiscordEmoji(W),U=Q.user??Q.member?.user;if(!U){this.logger.warn("Reaction event missing user info",{data:Q});return}let G={adapter:this,threadId:H,messageId:Q.message_id,emoji:K,rawEmoji:Q.emoji.id?`<:${W}:${Q.emoji.id}>`:W,added:w,user:{userId:U.id,userName:U.username,fullName:U.username,isBot:U.bot===!0,isMe:U.id===this.applicationId},raw:Q};this.chat.processReaction(G)}async postMessage(Q,w){let{channelId:$,threadId:B}=this.decodeThreadId(Q),X=Q;if(B)$=B;let Y={},Z=[],H=[],W=r70(w);if(W){let V=Vp0(W);Z.push(...V.embeds),H.push(...V.components)}else Y.content=this.truncateContent(wP(this.formatConverter.renderPostable(w),"discord"));if(Z.length>0)Y.embeds=Z;if(H.length>0)Y.components=H;let K=ol0(w),U=this.tryPostSlashResponse(X,Y,K);if(U)return U;if(K.length>0)return this.postMessageWithFiles($,X,Y,K);this.logger.debug("Discord API: POST message",{channelId:$,contentLength:Y.content?.length||0,embedCount:Z.length,componentCount:H.length});let q=await(await this.discordFetch(`/channels/${$}/messages`,"POST",Y)).json();return this.logger.debug("Discord API: POST message response",{messageId:q.id}),{id:q.id,threadId:X,raw:q}}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 W=await(B.length>0?await this.discordInteractionFetchWithFiles(Y,Z,$,B):await this.discordInteractionFetch(Y,Z,$)).json();return{id:W.id,threadId:w,raw:W}}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 mb&&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<=Sh1)return Q;return`${Q.slice(0,Sh1-3)}...`}async postMessageWithFiles(Q,w,$,B){let X=new FormData;X.append("payload_json",JSON.stringify($));for(let H=0;H<B.length;H++){let W=B[H];if(!W)continue;let K=await sl0(W.data,{platform:"discord"});if(!K)continue;let U=new Blob([new Uint8Array(K)],{type:W.mimeType||"application/octet-stream"});X.append(`files[${H}]`,U,W.filename)}let Y=await fetch(`${o70}/channels/${Q}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.botToken}`},body:X});if(!Y.ok){let H=await Y.text();throw new mb("discord",`Failed to post message: ${Y.status} ${H}`)}let Z=await Y.json();return{id:Z.id,threadId:w,raw:Z}}async discordInteractionFetch(Q,w,$){let B=await fetch(`${o70}${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 mb("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 H=B[Z];if(!H)continue;let W=await sl0(H.data,{platform:"discord"});if(!W)continue;let K=new Blob([new Uint8Array(W)],{type:H.mimeType||"application/octet-stream"});X.append(`files[${Z}]`,K,H.filename)}let Y=await fetch(`${o70}${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 mb("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={},H=[],W=[],K=r70($);if(K){let q=Vp0(K);H.push(...q.embeds),W.push(...q.components),Z.content=""}else Z.content=this.truncateContent(wP(this.formatConverter.renderPostable($),"discord"));if(H.length>0)Z.embeds=H;if(W.length>0)Z.components=W;this.logger.debug("Discord API: PATCH message",{channelId:Y,messageId:w,contentLength:Z.content?.length||0});let G=await(await this.discordFetch(`/channels/${Y}/messages/${w}`,"PATCH",Z)).json();return this.logger.debug("Discord API: PATCH message response",{messageId:G.id}),{id:G.id,threadId:Q,raw:G}}async deleteMessage(Q,w){let{channelId:$,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=tn.toDiscord?tn.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",H=new URLSearchParams;if(H.set("limit",String(Y)),w.cursor)if(Z==="backward")H.set("before",w.cursor);else H.set("after",w.cursor);this.logger.debug("Discord API: GET messages",{channelId:X,limit:Y,direction:Z,cursor:w.cursor});let K=await(await this.discordFetch(`/channels/${X}/messages?${H.toString()}`,"GET")).json();this.logger.debug("Discord API: GET messages response",{messageCount:K.length});let G=[...K].reverse().map((V)=>this.parseDiscordMessage(V,Q)),q;if(K.length===Y)if(Z==="backward")q=K.at(-1)?.id;else q=K[0]?.id;return{messages:G,nextCursor:q}}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===YP.DM||X.type===YP.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 rW("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===gM1.ThreadStarterMessage&&Q.referenced_message?Q.referenced_message:Q,B=$.author,X=B.bot??!1,Y=B.id===this.botUserId;return new q5({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 mb("discord","Failed to download Discord attachment",$ instanceof Error?$:void 0)}if(!w.ok)throw new mb("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 mb("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 j7.Client({intents:[j7.GatewayIntentBits.Guilds,j7.GatewayIntentBits.GuildMessages,j7.GatewayIntentBits.MessageContent,j7.GatewayIntentBits.DirectMessages,j7.GatewayIntentBits.GuildMessageReactions,j7.GatewayIntentBits.DirectMessageReactions],partials:[j7.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(j7.Events.ClientReady,()=>{this.logger.info("Discord Gateway connected",{username:B.user?.username,id:B.user?.id})}),B.on(j7.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(j7.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(j7.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(j7.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(j7.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 K=await this.createDiscordThread(B,Q.id);Y=K.id,this.logger.debug("Created Discord thread for incoming mention",{channelId:B,messageId:Q.id,threadId:K.id})}catch(K){this.logger.error("Failed to create Discord thread for mention",{error:String(K),messageId:Q.id})}let H=this.encodeThreadId({guildId:$,channelId:Z,threadId:Y}),W=new q5({id:Q.id,threadId:H,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.displayName||Q.author.username,isBot:Q.author.bot,isMe:!1},metadata:{dateSent:Q.createdAt,edited:Q.editedAt!==null,editedAt:Q.editedAt??void 0},attachments:Q.attachments.map((K)=>({type:this.getAttachmentType(K.contentType),url:K.url,name:K.name,mimeType:K.contentType??void 0,size:K.size})),raw:{id:Q.id,channel_id: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,H,W)}catch(K){this.logger.error("Error handling Gateway message",{error:String(K),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,H;if(Y&&Q.message.channel?.parentId)H=X,Z=Q.message.channel.parentId;let W=this.encodeThreadId({guildId:B,channelId:Z,threadId:H}),K=Q.emoji.name||"unknown",U=this.normalizeDiscordEmoji(K),G={adapter:this,threadId:W,messageId:Q.message.id,emoji:U,rawEmoji:Q.emoji.id?`<:${K}:${Q.emoji.id}>`:K,added:$,user:{userId:w.id,userName:w.username,fullName:w.username,isBot:w.bot===!0,isMe:w.id===this.applicationId},raw:{emoji:Q.emoji,message_id:Q.message.id,channel_id:Q.message.channelId,guild_id:Q.message.guildId,user_id:w.id}};this.chat.processReaction(G)}channelIdFromThreadId(Q){return Q.split(":").slice(0,3).join(":")}async fetchChannelMessages(Q,w={}){let B=Q.split(":")[2];if(!B)throw new rW("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 W=await(await this.discordFetch(`/channels/${B}/messages?${Z.toString()}`,"GET")).json();this.logger.debug("Discord API: GET channel messages response",{messageCount:W.length});let U=[...W].reverse().map((q)=>this.parseDiscordMessage(q,Q)),G;if(W.length===X)if(Y==="backward")G=W.at(-1)?.id;else G=W[0]?.id;return{messages:U,nextCursor:G}}async listThreads(Q,w={}){let $=Q.split(":"),B=$[1],X=$[2];if(!(B&&X))throw new rW("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET threads",{guildId:B,channelId:X});let H=((await(await this.discordFetch(`/guilds/${B}/threads/active`,"GET")).json()).threads||[]).filter((F)=>F.parent_id===X),W=[];try{W=(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 K=[...H,...W],U=new Set,G=K.filter((F)=>{if(U.has(F.id))return!1;return U.add(F.id),!0}),q=w.limit||50,V=G.slice(0,q),J=[];for(let F of V){let k=this.encodeThreadId({guildId:B,channelId:X,threadId:F.id});try{let O=(await(await this.discordFetch(`/channels/${F.id}/messages?limit=1&after=0`,"GET")).json())[0];if(O)J.push({id:k,rootMessage:this.parseDiscordMessage(O,k),replyCount:F.total_message_sent??F.message_count,lastReplyAt:F.thread_metadata?.archive_timestamp?new Date(F.thread_metadata.archive_timestamp):void 0})}catch{J.push({id:k,rootMessage:new q5({id:F.id,threadId:k,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:J.length}),{threads:J,nextCursor:G.length>q?String(q):void 0}}async fetchChannelInfo(Q){let $=Q.split(":")[2];if(!$)throw new rW("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===YP.DM||X.type===YP.GroupDM,memberCount:X.member_count,metadata:{channelType:X.type,raw:X}}}async postChannelMessage(Q,w){let B=Q.split(":")[2];if(!B)throw new rW("discord",`Invalid Discord channel ID: ${Q}`);let X={},Y=[],Z=[],H=r70(w);if(H){let q=Vp0(H);Y.push(...q.embeds),Z.push(...q.components)}else X.content=this.truncateContent(wP(this.formatConverter.renderPostable(w),"discord"));if(Y.length>0)X.embeds=Y;if(Z.length>0)X.components=Z;let W=ol0(w),K=this.tryPostSlashResponse(Q,X,W);if(K)return K;if(W.length>0)return this.postMessageWithFiles(B,Q,X,W);this.logger.debug("Discord API: POST channel message",{channelId:B,contentLength:X.content?.length||0});let G=await(await this.discordFetch(`/channels/${B}/messages`,"POST",X)).json();return{id:G.id,threadId:Q,raw:G}}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 Sb($)}};function ch1(A){return new MaQ(A??{})}var OaQ=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:xaQ(),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 xaQ(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function s70(A){return new OaQ}C0();var RaQ=f.object({subscribedAt:f.string().datetime(),routingMode:f.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:f.boolean().optional()}),vaQ="chat.discord.subscriptions";function Jp0(A){return A.scoped({namespace:vaQ,schema:RaQ})}function lh1(A,Q=s70()){let w=Jp0(A);return new ph1(Q,w)}class ph1{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 ih1(A){let{discord:Q}=A;if(!Q)return new dl0({userName:A.userName,adapters:{},state:s70()});let w=ch1({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds});return A.gatewayLoop.setAdapter(w),new dl0({userName:A.userName,adapters:{discord:w},concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"},state:lh1(A.runtimeState)})}class Fp0{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}}}fA();class Ip0{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 H=Z.name;if(!H)continue;let W=W3(H,"upload"),K=TF(W,Z.mimeType),U=Z.size??0,G=XQ0(W,K);if(!G){B.notices.push(`Unsupported file upload type: ${W}`);continue}if(!YQ0(G,U)){B.notices.push(`File upload too large: ${W}`);continue}try{let q=await this.readAttachmentData(Z);if(!q)continue;let V=K3({filename:W,mediaType:K,content:q,fallbackFilename:"upload"});if(!V.ok){B.notices.push(V.message);continue}let J=await Y.save({filename:V.filename,mediaType:V.mediaType,content:q,metadata:this.buildMetadata(A,Q,w)});B.attachments.push(nh1(J.filename,J.mediaType,q,J.ref,V.kind==="text"))}catch(q){this.deps.logger.error("Failed to read chat attachment",{error:q,filename:W}),B.notices.push(`Could not read file upload: ${W}`)}}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 dh1(A,Q,w,$){return nh1(A,Q,w,$,SF(A,Q))}function nh1(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 Br(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function Hq(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 haQ(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 rh1(A,Q){if(A.isDM)return!1;let w=Hq(A.id);if(!w.threadId)return!1;let $=haQ(Q);return $!==void 0&&$!==w.threadId}function a70(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let w=Hq(A.id);return[A.id,A.channelId,w.channelId,w.threadId].some(($)=>typeof $==="string"&&Q.allowedChannels.includes($))}function bp0(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 a70(A,w)}function Lp0(A,Q,w){if(Q!=="discord")return!0;if(!w)return!1;if(A.isDM&&!w.allowDMs)return!1;return a70(A,w)}function kp0(A,Q){return{channelId:Hq(A.id).channelId??A.channelId,isBot:Boolean(Q.author.isBot)}}function ny(A){return A.isDM?"DM":A.channelId}var CaQ="https://discord.com/api/v10";async function oh1(A){let Q=Hq(A.threadId),w=Q.threadId??Q.channelId;if(!w)return;let $=A.fetchFn??fetch;try{let B=await $(`${CaQ}/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 sh1={name:"@brains/chat",version:"0.2.0-alpha.168",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 gaQ=/https?:\/\/\S+/i,EaQ=/[\s\S]+/,TaQ=1000,SaQ=f.looseObject({type:f.literal("card"),children:f.array(f.looseObject({type:f.string()})),imageUrl:f.string().optional(),subtitle:f.string().optional(),title:f.string().optional()}),maQ=f.object({card:f.custom((A)=>SaQ.safeParse(A).success),fallbackText:f.string().optional()});class t70 extends aK{threadRegistry=new y70;pendingApprovals;uploadContinuity;promptActions=new Lc0(TaQ);toolStatusMessenger=new kc0(this.threadRegistry);cardBuilder=new Pc0({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new Oc0({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new xc0({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let w=this.config.adapters.discord?.botToken;if(!w)return;await oh1({threadId:A,messageId:Q,botToken:w,logger:this.logger})}});subscriptionRouter=new Fp0({getSubscriptions:()=>this.discordSubscriptions,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:rh1,logger:this.logger});chatInputBuilder=new Ip0({getUploadStore:()=>this.context?.uploads.scoped(Br()),getThreadIdParts:Hq,logger:this.logger});gatewayLoop;discordApp;discordSubscriptions;constructor(A={}){super("chat",sh1,A,bc0);this.gatewayLoop=new Rc0({getApp:()=>this.discordApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.discordApp=new vc0({discord:this.config.adapters.discord,getUploadStore:()=>this.context?.uploads.scoped(Br()),buildApp:(Q)=>ih1({userName:this.config.userName,discord:this.config.adapters.discord,gatewayLoop:this.gatewayLoop,runtimeState:Q})}),this.pendingApprovals=new pu({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 su({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(Br());if(!w)throw Error("Chat upload store unavailable");let $=await w.read(Q);return dh1($.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=Jp0(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 dn(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 dn(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=maQ.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 jc0(A)}formatCompletionOutput(A){return jc0(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 LL1(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&&bp0(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(EaQ,async(Q,w,$)=>{await this.handleRoutedMessage(Q,w,$)});A.onNewMessage(gaQ,async(Q,w)=>{await this.handlePassiveUrlCapture(Q,w)}),A.onAction([g70,_c0],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(Nc0,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(!Lp0(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=Hq(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 H=await this.context.agent.chat($.prompt,Y,{userPermissionLevel:X,interfaceType:Q,channelId:Z,channelName:ny(w),...this.buildActionEventMetadata(Q,w,A)});await this.renderAgentResponse({thread:w,channelId:Z,conversationId:Y,response:H,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(!Lp0(B,Q,this.config.adapters.discord))return;let X=Hq(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===g70,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(!bp0(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 dn(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=kp0(Q,w),Z=this.context.permissions.getUserLevel(A,w.author.userId,Y),H=await this.chatInputBuilder.build(A,Q,w,Z),W=[...H.attachments];if(await this.attachPriorUploads(B,H,Z),await this.postUploadNotices(Q,H.notices),!H.message&&H.attachments.length===0)return;this.rememberUploadAttachments(B,W),await this.runAgentTurn({thread:Q,channelId:X,logLabel:"Error handling chat message",body:async()=>{if(!this.context)return;let K=await this.getPendingApprovalIds(B);if(K.size>0){if(await this.handleConfirmationResponse(H.message,B,Q,K,Z,this.buildUserMessageMetadata(A,Q,w)))return}let U=this.buildCoalescedAgentInput(H.message,$),G=await this.context.agent.chat(U.message,B,{userPermissionLevel:Z,interfaceType:A,channelId:X,channelName:ny(Q),...this.buildUserMessageMetadata(A,Q,w,U.metadata),...H.attachments.length>0?{attachments:H.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:X,conversationId:B,response:G,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=C_(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((H)=>H.kind==="approvals");await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,Y?.confirmations);let Z=X??B;if(Z)for(let H of w.jobIds)this.trackAgentResponseForJob(H,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(!mu(A,$))return!1;let Y=d20({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:ny(A.thread),...A.metadata});if(this.removePendingApproval(A.conversationId,A.approvalId),!Q)return;await this.renderAgentResponse({thread:A.thread,channelId:A.thread.id,conversationId:A.conversationId,response:Q,userPermissionLevel:A.userPermissionLevel,confirmation:{approvalId:A.approvalId,confirmed:A.confirmed}})}formatNoticePayload(A,Q="Approval notice"){return{card:{type:"card",title:Q,children:[{type:"text",content:A}]},fallbackText:A}}formatErrorPayload(A){let Q=A instanceof Error?A.message:"Unknown error";return{card:{type:"card",title:"Message failed",children:[{type:"text",content:Q}]},fallbackText:`Message failed: ${Q}`}}formatAgentResponseText(A,Q){return A.directives.flatMap((w)=>{if(w.kind==="text")return[w.text];if(w.kind==="denied-artifact")return[this.cardBuilder.formatStructuredCard(w.card,Q)];return[]}).filter((w)=>w.trim().length>0).join(`
|
|
2369
|
+
\`\`\``;return this.defaultNodeToText(A,(Q)=>this.nodeToDiscordMarkdown(Q))}};var Th1={DeferredChannelMessageWithSource:5,DeferredUpdateMessage:6},o70="https://discord.com/api/v10",Sh1=2000,jaQ=/^[0-9a-f]{64}$/,PaQ=/^[0-9a-f]+$/,MaQ=class A{name="discord";userName;botUserId;apiBaseUrl;botToken;publicKey;applicationId;mentionRoleIds;interactionFlags;chat=null;logger;formatConverter=new NaQ;requestContext=new qaQ;threadParentCache=new Map;static THREAD_PARENT_CACHE_TTL=300000;constructor(Q={}){let w=Q.botToken??process.env.DISCORD_BOT_TOKEN;if(!w)throw new rW("discord","botToken is required. Set DISCORD_BOT_TOKEN or provide it in config.");let $=Q.publicKey??process.env.DISCORD_PUBLIC_KEY;if(!$)throw new rW("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 rW("discord","applicationId is required. Set DISCORD_APPLICATION_ID or provide it in config.");if(this.apiBaseUrl=Q.apiUrl??process.env.DISCORD_API_URL??o70,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 i70("info").child("discord"),this.userName=Q.userName??"bot",!jaQ.test(this.publicKey))this.logger.error("Invalid Discord public key format",{length:this.publicKey.length,isHex:PaQ.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 U=JSON.parse(X);return this.handleForwardedGatewayEvent(U,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"),H=Q.headers.get("x-signature-timestamp");if(!await this.verifySignature(B,Z,H))return this.logger.warn("Discord signature verification failed, returning 401"),new Response("Invalid signature",{status:401});this.logger.info("Discord signature verification passed");let K;try{K=JSON.parse(X)}catch{return new Response("Invalid JSON",{status:400})}if(this.logger.info("Discord interaction parsed",{type:K.type,typeIsPing:K.type===iy.Ping,expectedPingType:iy.Ping,id:K.id}),K.type===iy.Ping){let U=JSON.stringify({type:$r.InteractionResponseType.PONG});return this.logger.info("Discord PING received, responding with PONG",{responseBody:U,responseType:$r.InteractionResponseType.PONG}),new Response(U,{status:200,headers:{"Content-Type":"application/json"}})}if(K.type===iy.MessageComponent)return this.handleComponentInteraction(K,w),this.respondToInteraction({type:Th1.DeferredUpdateMessage});if(K.type===iy.ApplicationCommand){let U=this.getApplicationCommandContext(K),G=this.getInteractionFlags(U);return this.handleApplicationCommandInteraction(U,w),this.respondToInteraction({...G===void 0?{}:{data:{flags:G}},type:Th1.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 $r.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 H=Q.channel,W=H?.type===11||H?.type===12,K=W&&H?.parent_id?H.parent_id:X,U=W?this.encodeThreadId({guildId:Y,channelId:K,threadId:X}):this.encodeThreadId({guildId:Y,channelId:X}),G=VaQ($),q={actionId:G.actionId,value:G.value??G.actionId,user:{userId:B.id,userName:B.username,fullName:B.global_name||B.username,isBot:B.bot??!1,isMe:!1},messageId:Z,threadId:U,adapter:this,raw:Q};this.logger.debug("Processing Discord button action",{actionId:$,messageId:Z,threadId:U}),this.chat.processAction(q,w)}getApplicationCommandContext(Q){let w=Q.data?.name;if(!w)return this.logger.warn("No command name in application command interaction"),null;let $=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,H=Z&&Y?.parent_id?Y.parent_id:B,W=Z?this.encodeThreadId({guildId:X,channelId:H,threadId:B}):this.encodeThreadId({guildId:X,channelId:B}),{command:K,text:U}=this.parseSlashCommand(w,Q.data?.options);return{channelId:W,command:K,interaction:Q,text:U,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 q=await(await this.discordFetch(`/channels/${B}`,"GET")).json();if(q.parent_id)X=B,Y=q.parent_id,this.logger.debug("Fetched thread parent for forwarded message",{threadId:B,parentId:q.parent_id})}catch(G){this.logger.error("Failed to fetch thread parent",{error:String(G),channelId:B})}let Z=Q.is_mention||Q.mentions.some((G)=>G.id===this.applicationId),H=this.mentionRoleIds.length>0&&Q.mention_roles?.some((G)=>this.mentionRoleIds.includes(G)),W=Z||H;if(!X&&W)try{let G=await this.createDiscordThread(B,Q.id);X=G.id,this.logger.debug("Created Discord thread for forwarded mention",{channelId:B,messageId:Q.id,threadId:G.id})}catch(G){this.logger.error("Failed to create Discord thread for mention",{error:String(G),messageId:Q.id})}let K=this.encodeThreadId({guildId:$,channelId:Y,threadId:X}),U=new q5({id:Q.id,threadId:K,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.global_name||Q.author.username,isBot:Q.author.bot===!0,isMe:Q.author.id===this.applicationId},metadata:{dateSent:new Date(Q.timestamp),edited:!1},attachments:Q.attachments.map((G)=>({type:this.getAttachmentType(G.content_type),url:G.url,name:G.filename,mimeType:G.content_type,size:G.size})),raw:Q,isMention:W});try{await this.chat.handleIncomingMessage(this,K,U)}catch(G){this.logger.error("Error handling forwarded message",{error:String(G),messageId:Q.id})}}async handleForwardedReaction(Q,w,$){if(!this.chat)return;let B=Q.guild_id||"@me",X=Q.channel_id,Y,Z=X;if(Q.channel_type===YP.GuildPublicThread||Q.channel_type===YP.GuildPrivateThread){let q=this.threadParentCache.get(X);if(q&&q.expiresAt>Date.now())Y=X,Z=q.parentId;else try{let J=await(await this.discordFetch(`/channels/${X}`,"GET")).json();if(J.parent_id)Y=X,Z=J.parent_id,this.threadParentCache.set(X,{parentId:J.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 H=this.encodeThreadId({guildId:B,channelId:Z,threadId:Y}),W=Q.emoji.name||"unknown",K=this.normalizeDiscordEmoji(W),U=Q.user??Q.member?.user;if(!U){this.logger.warn("Reaction event missing user info",{data:Q});return}let G={adapter:this,threadId:H,messageId:Q.message_id,emoji:K,rawEmoji:Q.emoji.id?`<:${W}:${Q.emoji.id}>`:W,added:w,user:{userId:U.id,userName:U.username,fullName:U.username,isBot:U.bot===!0,isMe:U.id===this.applicationId},raw:Q};this.chat.processReaction(G)}async postMessage(Q,w){let{channelId:$,threadId:B}=this.decodeThreadId(Q),X=Q;if(B)$=B;let Y={},Z=[],H=[],W=r70(w);if(W){let V=Vp0(W);Z.push(...V.embeds),H.push(...V.components)}else Y.content=this.truncateContent(wP(this.formatConverter.renderPostable(w),"discord"));if(Z.length>0)Y.embeds=Z;if(H.length>0)Y.components=H;let K=ol0(w),U=this.tryPostSlashResponse(X,Y,K);if(U)return U;if(K.length>0)return this.postMessageWithFiles($,X,Y,K);this.logger.debug("Discord API: POST message",{channelId:$,contentLength:Y.content?.length||0,embedCount:Z.length,componentCount:H.length});let q=await(await this.discordFetch(`/channels/${$}/messages`,"POST",Y)).json();return this.logger.debug("Discord API: POST message response",{messageId:q.id}),{id:q.id,threadId:X,raw:q}}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 W=await(B.length>0?await this.discordInteractionFetchWithFiles(Y,Z,$,B):await this.discordInteractionFetch(Y,Z,$)).json();return{id:W.id,threadId:w,raw:W}}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 mb&&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<=Sh1)return Q;return`${Q.slice(0,Sh1-3)}...`}async postMessageWithFiles(Q,w,$,B){let X=new FormData;X.append("payload_json",JSON.stringify($));for(let H=0;H<B.length;H++){let W=B[H];if(!W)continue;let K=await sl0(W.data,{platform:"discord"});if(!K)continue;let U=new Blob([new Uint8Array(K)],{type:W.mimeType||"application/octet-stream"});X.append(`files[${H}]`,U,W.filename)}let Y=await fetch(`${o70}/channels/${Q}/messages`,{method:"POST",headers:{Authorization:`Bot ${this.botToken}`},body:X});if(!Y.ok){let H=await Y.text();throw new mb("discord",`Failed to post message: ${Y.status} ${H}`)}let Z=await Y.json();return{id:Z.id,threadId:w,raw:Z}}async discordInteractionFetch(Q,w,$){let B=await fetch(`${o70}${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 mb("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 H=B[Z];if(!H)continue;let W=await sl0(H.data,{platform:"discord"});if(!W)continue;let K=new Blob([new Uint8Array(W)],{type:H.mimeType||"application/octet-stream"});X.append(`files[${Z}]`,K,H.filename)}let Y=await fetch(`${o70}${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 mb("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={},H=[],W=[],K=r70($);if(K){let q=Vp0(K);H.push(...q.embeds),W.push(...q.components),Z.content=""}else Z.content=this.truncateContent(wP(this.formatConverter.renderPostable($),"discord"));if(H.length>0)Z.embeds=H;if(W.length>0)Z.components=W;this.logger.debug("Discord API: PATCH message",{channelId:Y,messageId:w,contentLength:Z.content?.length||0});let G=await(await this.discordFetch(`/channels/${Y}/messages/${w}`,"PATCH",Z)).json();return this.logger.debug("Discord API: PATCH message response",{messageId:G.id}),{id:G.id,threadId:Q,raw:G}}async deleteMessage(Q,w){let{channelId:$,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=tn.toDiscord?tn.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",H=new URLSearchParams;if(H.set("limit",String(Y)),w.cursor)if(Z==="backward")H.set("before",w.cursor);else H.set("after",w.cursor);this.logger.debug("Discord API: GET messages",{channelId:X,limit:Y,direction:Z,cursor:w.cursor});let K=await(await this.discordFetch(`/channels/${X}/messages?${H.toString()}`,"GET")).json();this.logger.debug("Discord API: GET messages response",{messageCount:K.length});let G=[...K].reverse().map((V)=>this.parseDiscordMessage(V,Q)),q;if(K.length===Y)if(Z==="backward")q=K.at(-1)?.id;else q=K[0]?.id;return{messages:G,nextCursor:q}}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===YP.DM||X.type===YP.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 rW("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===gM1.ThreadStarterMessage&&Q.referenced_message?Q.referenced_message:Q,B=$.author,X=B.bot??!1,Y=B.id===this.botUserId;return new q5({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 mb("discord","Failed to download Discord attachment",$ instanceof Error?$:void 0)}if(!w.ok)throw new mb("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 mb("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 j7.Client({intents:[j7.GatewayIntentBits.Guilds,j7.GatewayIntentBits.GuildMessages,j7.GatewayIntentBits.MessageContent,j7.GatewayIntentBits.DirectMessages,j7.GatewayIntentBits.GuildMessageReactions,j7.GatewayIntentBits.DirectMessageReactions],partials:[j7.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(j7.Events.ClientReady,()=>{this.logger.info("Discord Gateway connected",{username:B.user?.username,id:B.user?.id})}),B.on(j7.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(j7.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(j7.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(j7.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(j7.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 K=await this.createDiscordThread(B,Q.id);Y=K.id,this.logger.debug("Created Discord thread for incoming mention",{channelId:B,messageId:Q.id,threadId:K.id})}catch(K){this.logger.error("Failed to create Discord thread for mention",{error:String(K),messageId:Q.id})}let H=this.encodeThreadId({guildId:$,channelId:Z,threadId:Y}),W=new q5({id:Q.id,threadId:H,text:Q.content,formatted:this.formatConverter.toAst(Q.content),author:{userId:Q.author.id,userName:Q.author.username,fullName:Q.author.displayName||Q.author.username,isBot:Q.author.bot,isMe:!1},metadata:{dateSent:Q.createdAt,edited:Q.editedAt!==null,editedAt:Q.editedAt??void 0},attachments:Q.attachments.map((K)=>({type:this.getAttachmentType(K.contentType),url:K.url,name:K.name,mimeType:K.contentType??void 0,size:K.size})),raw:{id:Q.id,channel_id: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,H,W)}catch(K){this.logger.error("Error handling Gateway message",{error:String(K),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,H;if(Y&&Q.message.channel?.parentId)H=X,Z=Q.message.channel.parentId;let W=this.encodeThreadId({guildId:B,channelId:Z,threadId:H}),K=Q.emoji.name||"unknown",U=this.normalizeDiscordEmoji(K),G={adapter:this,threadId:W,messageId:Q.message.id,emoji:U,rawEmoji:Q.emoji.id?`<:${K}:${Q.emoji.id}>`:K,added:$,user:{userId:w.id,userName:w.username,fullName:w.username,isBot:w.bot===!0,isMe:w.id===this.applicationId},raw:{emoji:Q.emoji,message_id:Q.message.id,channel_id:Q.message.channelId,guild_id:Q.message.guildId,user_id:w.id}};this.chat.processReaction(G)}channelIdFromThreadId(Q){return Q.split(":").slice(0,3).join(":")}async fetchChannelMessages(Q,w={}){let B=Q.split(":")[2];if(!B)throw new rW("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 W=await(await this.discordFetch(`/channels/${B}/messages?${Z.toString()}`,"GET")).json();this.logger.debug("Discord API: GET channel messages response",{messageCount:W.length});let U=[...W].reverse().map((q)=>this.parseDiscordMessage(q,Q)),G;if(W.length===X)if(Y==="backward")G=W.at(-1)?.id;else G=W[0]?.id;return{messages:U,nextCursor:G}}async listThreads(Q,w={}){let $=Q.split(":"),B=$[1],X=$[2];if(!(B&&X))throw new rW("discord",`Invalid Discord channel ID: ${Q}`);this.logger.debug("Discord API: GET threads",{guildId:B,channelId:X});let H=((await(await this.discordFetch(`/guilds/${B}/threads/active`,"GET")).json()).threads||[]).filter((F)=>F.parent_id===X),W=[];try{W=(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 K=[...H,...W],U=new Set,G=K.filter((F)=>{if(U.has(F.id))return!1;return U.add(F.id),!0}),q=w.limit||50,V=G.slice(0,q),J=[];for(let F of V){let k=this.encodeThreadId({guildId:B,channelId:X,threadId:F.id});try{let O=(await(await this.discordFetch(`/channels/${F.id}/messages?limit=1&after=0`,"GET")).json())[0];if(O)J.push({id:k,rootMessage:this.parseDiscordMessage(O,k),replyCount:F.total_message_sent??F.message_count,lastReplyAt:F.thread_metadata?.archive_timestamp?new Date(F.thread_metadata.archive_timestamp):void 0})}catch{J.push({id:k,rootMessage:new q5({id:F.id,threadId:k,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:J.length}),{threads:J,nextCursor:G.length>q?String(q):void 0}}async fetchChannelInfo(Q){let $=Q.split(":")[2];if(!$)throw new rW("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===YP.DM||X.type===YP.GroupDM,memberCount:X.member_count,metadata:{channelType:X.type,raw:X}}}async postChannelMessage(Q,w){let B=Q.split(":")[2];if(!B)throw new rW("discord",`Invalid Discord channel ID: ${Q}`);let X={},Y=[],Z=[],H=r70(w);if(H){let q=Vp0(H);Y.push(...q.embeds),Z.push(...q.components)}else X.content=this.truncateContent(wP(this.formatConverter.renderPostable(w),"discord"));if(Y.length>0)X.embeds=Y;if(Z.length>0)X.components=Z;let W=ol0(w),K=this.tryPostSlashResponse(Q,X,W);if(K)return K;if(W.length>0)return this.postMessageWithFiles(B,Q,X,W);this.logger.debug("Discord API: POST channel message",{channelId:B,contentLength:X.content?.length||0});let G=await(await this.discordFetch(`/channels/${B}/messages`,"POST",X)).json();return{id:G.id,threadId:Q,raw:G}}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 Sb($)}};function ch1(A){return new MaQ(A??{})}var OaQ=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:xaQ(),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 xaQ(){return`mem_${Date.now()}_${Math.random().toString(36).substring(2,15)}`}function s70(A){return new OaQ}C0();var RaQ=f.object({subscribedAt:f.string().datetime(),routingMode:f.enum(["auto","mention-required"]).optional(),mentionRequiredNoticeSent:f.boolean().optional()}),vaQ="chat.discord.subscriptions";function Jp0(A){return A.scoped({namespace:vaQ,schema:RaQ})}function lh1(A,Q=s70()){let w=Jp0(A);return new ph1(Q,w)}class ph1{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 ih1(A){let{discord:Q}=A;if(!Q)return new dl0({userName:A.userName,adapters:{},state:s70()});let w=ch1({botToken:Q.botToken,publicKey:Q.publicKey,applicationId:Q.applicationId,mentionRoleIds:Q.mentionRoleIds});return A.gatewayLoop.setAdapter(w),new dl0({userName:A.userName,adapters:{discord:w},concurrency:{strategy:"queue",maxQueueSize:5,onQueueFull:"drop-oldest"},state:lh1(A.runtimeState)})}class Fp0{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}}}fA();class Ip0{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 H=Z.name;if(!H)continue;let W=W3(H,"upload"),K=TF(W,Z.mimeType),U=Z.size??0,G=XQ0(W,K);if(!G){B.notices.push(`Unsupported file upload type: ${W}`);continue}if(!YQ0(G,U)){B.notices.push(`File upload too large: ${W}`);continue}try{let q=await this.readAttachmentData(Z);if(!q)continue;let V=K3({filename:W,mediaType:K,content:q,fallbackFilename:"upload"});if(!V.ok){B.notices.push(V.message);continue}let J=await Y.save({filename:V.filename,mediaType:V.mediaType,content:q,metadata:this.buildMetadata(A,Q,w)});B.attachments.push(nh1(J.filename,J.mediaType,q,J.ref,V.kind==="text"))}catch(q){this.deps.logger.error("Failed to read chat attachment",{error:q,filename:W}),B.notices.push(`Could not read file upload: ${W}`)}}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 dh1(A,Q,w,$){return nh1(A,Q,w,$,SF(A,Q))}function nh1(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 Br(){return{namespace:"discord-chat",refKind:"discord-chat-upload",routePath:"/api/webhooks/chat/discord/uploads"}}function Hq(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 haQ(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 rh1(A,Q){if(A.isDM)return!1;let w=Hq(A.id);if(!w.threadId)return!1;let $=haQ(Q);return $!==void 0&&$!==w.threadId}function a70(A,Q){if(Q.allowedChannels.length===0||A.isDM)return!0;let w=Hq(A.id);return[A.id,A.channelId,w.channelId,w.threadId].some(($)=>typeof $==="string"&&Q.allowedChannels.includes($))}function bp0(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 a70(A,w)}function Lp0(A,Q,w){if(Q!=="discord")return!0;if(!w)return!1;if(A.isDM&&!w.allowDMs)return!1;return a70(A,w)}function kp0(A,Q){return{channelId:Hq(A.id).channelId??A.channelId,isBot:Boolean(Q.author.isBot)}}function ny(A){return A.isDM?"DM":A.channelId}var CaQ="https://discord.com/api/v10";async function oh1(A){let Q=Hq(A.threadId),w=Q.threadId??Q.channelId;if(!w)return;let $=A.fetchFn??fetch;try{let B=await $(`${CaQ}/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 sh1={name:"@brains/chat",version:"0.2.0-alpha.169",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 gaQ=/https?:\/\/\S+/i,EaQ=/[\s\S]+/,TaQ=1000,SaQ=f.looseObject({type:f.literal("card"),children:f.array(f.looseObject({type:f.string()})),imageUrl:f.string().optional(),subtitle:f.string().optional(),title:f.string().optional()}),maQ=f.object({card:f.custom((A)=>SaQ.safeParse(A).success),fallbackText:f.string().optional()});class t70 extends aK{threadRegistry=new y70;pendingApprovals;uploadContinuity;promptActions=new Lc0(TaQ);toolStatusMessenger=new kc0(this.threadRegistry);cardBuilder=new Pc0({getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),registerPromptAction:(A,Q)=>this.registerPromptAction(A,Q)});artifactDelivery=new Oc0({getContext:()=>this.context,getDisplayBaseUrl:()=>this.getPreferredDisplayBaseUrl(),logger:this.logger});approvalCards=new xc0({cardBuilder:this.cardBuilder,clearMessageComponents:async(A,Q)=>{let w=this.config.adapters.discord?.botToken;if(!w)return;await oh1({threadId:A,messageId:Q,botToken:w,logger:this.logger})}});subscriptionRouter=new Fp0({getSubscriptions:()=>this.discordSubscriptions,getPlatform:(A)=>this.getPlatform(A),isBotCreatedThread:rh1,logger:this.logger});chatInputBuilder=new Ip0({getUploadStore:()=>this.context?.uploads.scoped(Br()),getThreadIdParts:Hq,logger:this.logger});gatewayLoop;discordApp;discordSubscriptions;constructor(A={}){super("chat",sh1,A,bc0);this.gatewayLoop=new Rc0({getApp:()=>this.discordApp.instance,gatewayRunMs:this.config.gatewayRunMs,gatewayRestartDelayMs:this.config.gatewayRestartDelayMs,logger:this.logger}),this.discordApp=new vc0({discord:this.config.adapters.discord,getUploadStore:()=>this.context?.uploads.scoped(Br()),buildApp:(Q)=>ih1({userName:this.config.userName,discord:this.config.adapters.discord,gatewayLoop:this.gatewayLoop,runtimeState:Q})}),this.pendingApprovals=new pu({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 su({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(Br());if(!w)throw Error("Chat upload store unavailable");let $=await w.read(Q);return dh1($.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=Jp0(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 dn(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 dn(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=maQ.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 jc0(A)}formatCompletionOutput(A){return jc0(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 LL1(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&&bp0(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(EaQ,async(Q,w,$)=>{await this.handleRoutedMessage(Q,w,$)});A.onNewMessage(gaQ,async(Q,w)=>{await this.handlePassiveUrlCapture(Q,w)}),A.onAction([g70,_c0],async(Q)=>{await this.handleApprovalAction(Q)}),A.onAction(Nc0,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(!Lp0(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=Hq(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 H=await this.context.agent.chat($.prompt,Y,{userPermissionLevel:X,interfaceType:Q,channelId:Z,channelName:ny(w),...this.buildActionEventMetadata(Q,w,A)});await this.renderAgentResponse({thread:w,channelId:Z,conversationId:Y,response:H,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(!Lp0(B,Q,this.config.adapters.discord))return;let X=Hq(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===g70,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(!bp0(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 dn(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=kp0(Q,w),Z=this.context.permissions.getUserLevel(A,w.author.userId,Y),H=await this.chatInputBuilder.build(A,Q,w,Z),W=[...H.attachments];if(await this.attachPriorUploads(B,H,Z),await this.postUploadNotices(Q,H.notices),!H.message&&H.attachments.length===0)return;this.rememberUploadAttachments(B,W),await this.runAgentTurn({thread:Q,channelId:X,logLabel:"Error handling chat message",body:async()=>{if(!this.context)return;let K=await this.getPendingApprovalIds(B);if(K.size>0){if(await this.handleConfirmationResponse(H.message,B,Q,K,Z,this.buildUserMessageMetadata(A,Q,w)))return}let U=this.buildCoalescedAgentInput(H.message,$),G=await this.context.agent.chat(U.message,B,{userPermissionLevel:Z,interfaceType:A,channelId:X,channelName:ny(Q),...this.buildUserMessageMetadata(A,Q,w,U.metadata),...H.attachments.length>0?{attachments:H.attachments}:{}});await this.renderAgentResponse({thread:Q,channelId:X,conversationId:B,response:G,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=C_(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((H)=>H.kind==="approvals");await this.approvalCards.trackPendingConfirmations(A.thread,A.conversationId,Y?.confirmations);let Z=X??B;if(Z)for(let H of w.jobIds)this.trackAgentResponseForJob(H,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(!mu(A,$))return!1;let Y=d20({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:ny(A.thread),...A.metadata});if(this.removePendingApproval(A.conversationId,A.approvalId),!Q)return;await this.renderAgentResponse({thread:A.thread,channelId:A.thread.id,conversationId:A.conversationId,response:Q,userPermissionLevel:A.userPermissionLevel,confirmation:{approvalId:A.approvalId,confirmed:A.confirmed}})}formatNoticePayload(A,Q="Approval notice"){return{card:{type:"card",title:Q,children:[{type:"text",content:A}]},fallbackText:A}}formatErrorPayload(A){let Q=A instanceof Error?A.message:"Unknown error";return{card:{type:"card",title:"Message failed",children:[{type:"text",content:Q}]},fallbackText:`Message failed: ${Q}`}}formatAgentResponseText(A,Q){return A.directives.flatMap((w)=>{if(w.kind==="text")return[w.text];if(w.kind==="denied-artifact")return[this.cardBuilder.formatStructuredCard(w.card,Q)];return[]}).filter((w)=>w.trim().length>0).join(`
|
|
2370
2370
|
|
|
2371
2371
|
`)}formatConfirmationResponsePayload(A,Q,w,$){let B=QQ0({response:A,confirmed:Q,remainingApprovalHelp:w,deniedCardIds:$,formatCard:(X)=>this.cardBuilder.formatStructuredCard(X,$),formatPendingConfirmationHelp:MR});return{card:{type:"card",title:e20(B.variant),children:B.parts.map((X)=>({type:"text",content:X}))},fallbackText:B.parts.join(`
|
|
2372
2372
|
|
|
@@ -2438,7 +2438,7 @@ ${vl0(A)}
|
|
|
2438
2438
|
<p>Once built, this page will be replaced with your actual website.</p>
|
|
2439
2439
|
</div>
|
|
2440
2440
|
</body>
|
|
2441
|
-
</html>`;var hC1={name:"@brains/webserver",version:"0.2.0-alpha.168",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 cb extends UD{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",hC1,A,up0)}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 W40({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&&!CC1(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(yC1(this.config.previewDistDir,"index.html"),cp0),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!CC1(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(yC1(this.config.productionDistDir,"index.html"),cp0),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}Q$();fA();C0();s_();var gC1={name:"@brains/web-chat",version:"0.2.0-alpha.168",description:"Web chat interface for Brains",dependencies:{"@ai-sdk/react":"^3.0.208","@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@streamdown/cjk":"^1.0.3","@streamdown/code":"^1.1.1","@streamdown/math":"^1.0.2","@streamdown/mermaid":"^1.0.2",ai:"^6.0.206","class-variance-authority":"^0.7.0",cmdk:"^1.1.1","lucide-react":"^1.20.0",nanoid:"^5.0.4","radix-ui":"^1.6.0",react:"^19.2.7","react-dom":"^19.2.7",shiki:"^4.2.0",streamdown:"^2.5.0","tailwind-merge":"^3.6.0","use-stick-to-bottom":"^1.1.6"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3",typescript:"^7.0.2",vite:"^8.0.16"},exports:{".":"./src/index.ts"},files:["src","dist","package.json"],private:!0,scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json"},type:"module"};fA();async function EC1(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 SC1({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=Y3("document",X.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let Z=Z3(X.metadata,B,"document",Y.mimeType);return mC1({requestUrl:$,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function TC1(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 SC1({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=Y3("image",X.content);if(!Y)return new Response("Image content is not an image",{status:415});let Z=Z3(X.metadata,B,"image",Y.mimeType);return mC1({requestUrl:$,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function SC1(A){let Q={entityType:A.entityType,id:A.id},w=await f3({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 mC1(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":gF({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}C0();fA();var Kr="upload",uC1=JR;var ytQ={namespace:"upload",refKind:Kr,routePath:"/api/chat/uploads"};function K40(){return ytQ}fA();C_0();var cC1=$Q0;var lC1=BQ0;var gtQ="file",EtQ=16384;async function pC1(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>lC1+EtQ)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(gtQ);if(!(B instanceof File))return new Response("Missing upload file",{status:400});let X=Buffer.from(await B.arrayBuffer()),Y=K3({filename:B.name,mediaType:B.type,content:X});if(!Y.ok)return new Response(Y.message,{status:400});let Z=Q.getUploadStore(),H=await Z.save({filename:Y.filename,mediaType:Y.mediaType,content:X});return Response.json(Z.toResponseBody(H),{status:201})}async function iC1(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 rC1(w,Q.getUploadStore());if($ instanceof Response)return $;let{record:B,content:X}=$,Y=oC1(B,X);if(Y instanceof Response)return Y;let Z=new URL(A.url).searchParams.has("download")?"attachment":"inline",H=new Uint8Array(X).buffer;return new Response(H,{headers:{"Content-Type":B.mediaType,"Content-Length":String(X.byteLength),"Content-Disposition":gF({disposition:Z,filename:B.filename})}})}function dC1(A){let Q=W3(A.filename??cC1),w=StQ(A.url);if(!w)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let $=K3({filename:Q,mediaType:A.mediaType,content:w.buffer});if(!$.ok)return new Response($.message,{status:400});return sC1($,w.buffer)}async function nC1(A,Q){let w=await rC1(A,Q);if(w instanceof Response)return w;let{record:$,content:B}=w,X=oC1($,B);if(X instanceof Response)return X;return sC1(X,B,{kind:Kr,id:A})}async function rC1(A,Q){try{return await Q.read(A)}catch(w){if(w instanceof GD)return TtQ(w);throw w}}function oC1(A,Q){let w=K3({filename:A.filename,mediaType:A.mediaType,content:Q});if(!w.ok)return new Response(w.message,{status:400});return w}function sC1(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 TtQ(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 StQ(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 mtQ=f.object({type:f.literal("text"),text:f.string()}),utQ=f.object({type:f.literal("file"),mediaType:f.string().optional(),filename:f.string().optional(),url:f.string()}),ctQ=f.looseObject({state:f.literal("approval-responded"),approval:f.object({id:f.string(),approved:f.boolean()})}),ltQ=f.object({id:f.string().optional(),role:f.string(),parts:f.array(f.unknown()).optional(),content:f.string().optional()}),aC1=f.object({id:f.string().optional(),messages:f.array(ltQ).min(1),trigger:f.string().optional()}),ptQ=f.object({kind:f.literal(Kr),id:f.string().regex(uC1)}),itQ=f.object({type:f.literal("data-upload"),data:f.object({ref:ptQ})});async function tC1(A,Q){let w=dtQ(A);if(!w)return{message:"",attachments:[]};let $=[],B=[];for(let Y of w.parts??[]){let Z=mtQ.safeParse(Y);if(Z.success){if(Z.data.text.length>0)$.push(Z.data.text);continue}let H=utQ.safeParse(Y);if(H.success){let K=dC1(H.data);if(K instanceof Response)return K;B.push(K);continue}let W=itQ.safeParse(Y);if(W.success){let K=await nC1(W.data.data.ref.id,Q.uploadStore);if(K instanceof Response)return K;B.push(K);continue}if(ntQ(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:$.length>0?$.join(`
|
|
2441
|
+
</html>`;var hC1={name:"@brains/webserver",version:"0.2.0-alpha.169",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 cb extends UD{serverManager;siteUrl;previewUrl;constructor(A={}){super("webserver",hC1,A,up0)}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 W40({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&&!CC1(this.config.previewDistDir))await A(this.config.previewDistDir,{recursive:!0}),await Q(yC1(this.config.previewDistDir,"index.html"),cp0),this.logger.debug(`Created preview directory at ${this.config.previewDistDir}`);if(!CC1(this.config.productionDistDir))await A(this.config.productionDistDir,{recursive:!0}),await Q(yC1(this.config.productionDistDir,"index.html"),cp0),this.logger.debug(`Created production directory at ${this.config.productionDistDir}`)}}Q$();fA();C0();s_();var gC1={name:"@brains/web-chat",version:"0.2.0-alpha.169",description:"Web chat interface for Brains",dependencies:{"@ai-sdk/react":"^3.0.208","@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@streamdown/cjk":"^1.0.3","@streamdown/code":"^1.1.1","@streamdown/math":"^1.0.2","@streamdown/mermaid":"^1.0.2",ai:"^6.0.206","class-variance-authority":"^0.7.0",cmdk:"^1.1.1","lucide-react":"^1.20.0",nanoid:"^5.0.4","radix-ui":"^1.6.0",react:"^19.2.7","react-dom":"^19.2.7",shiki:"^4.2.0",streamdown:"^2.5.0","tailwind-merge":"^3.6.0","use-stick-to-bottom":"^1.1.6"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3",typescript:"^7.0.2",vite:"^8.0.16"},exports:{".":"./src/index.ts"},files:["src","dist","package.json"],private:!0,scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json"},type:"module"};fA();async function EC1(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 SC1({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=Y3("document",X.content);if(!Y)return new Response("Document content is not a PDF",{status:415});let Z=Z3(X.metadata,B,"document",Y.mimeType);return mC1({requestUrl:$,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function TC1(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 SC1({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=Y3("image",X.content);if(!Y)return new Response("Image content is not an image",{status:415});let Z=Z3(X.metadata,B,"image",Y.mimeType);return mC1({requestUrl:$,data:Y.data,mediaType:Y.mimeType,filename:Z})}async function SC1(A){let Q={entityType:A.entityType,id:A.id},w=await f3({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 mC1(A){let Q=new Headers({"Content-Type":A.mediaType,"Content-Length":String(A.data.byteLength),"Content-Disposition":gF({disposition:A.requestUrl.searchParams.has("download")?"attachment":"inline",filename:A.filename})});return new Response(A.data,{headers:Q})}C0();fA();var Kr="upload",uC1=JR;var ytQ={namespace:"upload",refKind:Kr,routePath:"/api/chat/uploads"};function K40(){return ytQ}fA();C_0();var cC1=$Q0;var lC1=BQ0;var gtQ="file",EtQ=16384;async function pC1(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>lC1+EtQ)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(gtQ);if(!(B instanceof File))return new Response("Missing upload file",{status:400});let X=Buffer.from(await B.arrayBuffer()),Y=K3({filename:B.name,mediaType:B.type,content:X});if(!Y.ok)return new Response(Y.message,{status:400});let Z=Q.getUploadStore(),H=await Z.save({filename:Y.filename,mediaType:Y.mediaType,content:X});return Response.json(Z.toResponseBody(H),{status:201})}async function iC1(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 rC1(w,Q.getUploadStore());if($ instanceof Response)return $;let{record:B,content:X}=$,Y=oC1(B,X);if(Y instanceof Response)return Y;let Z=new URL(A.url).searchParams.has("download")?"attachment":"inline",H=new Uint8Array(X).buffer;return new Response(H,{headers:{"Content-Type":B.mediaType,"Content-Length":String(X.byteLength),"Content-Disposition":gF({disposition:Z,filename:B.filename})}})}function dC1(A){let Q=W3(A.filename??cC1),w=StQ(A.url);if(!w)return new Response(`Unsupported file upload URL: ${Q}`,{status:400});let $=K3({filename:Q,mediaType:A.mediaType,content:w.buffer});if(!$.ok)return new Response($.message,{status:400});return sC1($,w.buffer)}async function nC1(A,Q){let w=await rC1(A,Q);if(w instanceof Response)return w;let{record:$,content:B}=w,X=oC1($,B);if(X instanceof Response)return X;return sC1(X,B,{kind:Kr,id:A})}async function rC1(A,Q){try{return await Q.read(A)}catch(w){if(w instanceof GD)return TtQ(w);throw w}}function oC1(A,Q){let w=K3({filename:A.filename,mediaType:A.mediaType,content:Q});if(!w.ok)return new Response(w.message,{status:400});return w}function sC1(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 TtQ(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 StQ(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 mtQ=f.object({type:f.literal("text"),text:f.string()}),utQ=f.object({type:f.literal("file"),mediaType:f.string().optional(),filename:f.string().optional(),url:f.string()}),ctQ=f.looseObject({state:f.literal("approval-responded"),approval:f.object({id:f.string(),approved:f.boolean()})}),ltQ=f.object({id:f.string().optional(),role:f.string(),parts:f.array(f.unknown()).optional(),content:f.string().optional()}),aC1=f.object({id:f.string().optional(),messages:f.array(ltQ).min(1),trigger:f.string().optional()}),ptQ=f.object({kind:f.literal(Kr),id:f.string().regex(uC1)}),itQ=f.object({type:f.literal("data-upload"),data:f.object({ref:ptQ})});async function tC1(A,Q){let w=dtQ(A);if(!w)return{message:"",attachments:[]};let $=[],B=[];for(let Y of w.parts??[]){let Z=mtQ.safeParse(Y);if(Z.success){if(Z.data.text.length>0)$.push(Z.data.text);continue}let H=utQ.safeParse(Y);if(H.success){let K=dC1(H.data);if(K instanceof Response)return K;B.push(K);continue}let W=itQ.safeParse(Y);if(W.success){let K=await nC1(W.data.data.ref.id,Q.uploadStore);if(K instanceof Response)return K;B.push(K);continue}if(ntQ(Y)==="data-upload")return new Response("Invalid upload ref",{status:400})}return{message:$.length>0?$.join(`
|
|
2442
2442
|
|
|
2443
2443
|
`):w.content??"",attachments:B,...w.id?{messageId:w.id}:{}}}function eC1(A){let Q=A.messages.at(-1);if(!Q||Q.role==="user")return[];return(Q.parts??[]).map((w)=>ctQ.safeParse(w)).filter((w)=>w.success).map((w)=>w.data.approval)}function dtQ(A){for(let Q=A.messages.length-1;Q>=0;Q-=1){let w=A.messages[Q];if(w?.role==="user")return w}return}function ntQ(A){if(typeof A!=="object"||A===null||!("type"in A))return;let Q=A.type;return typeof Q==="string"?Q:void 0}fA();var rtQ=/\n{0,2}\[Entities affected this turn: [\s\S]*? Reference these IDs directly in follow-ups instead of searching for them\.\]\s*$/;function U40(A){return A.replace(rtQ,"").trimEnd()}fA();function Ay1(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 lp0(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=WQ0($);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}
|
|
2444
2444
|
|
|
@@ -5729,7 +5729,7 @@ ${Ky1}</style></head><body>${Gr(A)}<main id="root" data-web-chat-root>Brain Chat
|
|
|
5729
5729
|
`);B=Y.pop()??"";for(let Z of Y){let H=Z.split(`
|
|
5730
5730
|
`).find((J)=>J.startsWith("data: "));if(!H)continue;let W;try{let J=TeQ.safeParse(JSON.parse(H.slice(6)));if(!J.success)continue;W=J.data}catch{return w.cancel().catch(()=>{}),{success:!1,error:"Malformed SSE event from remote agent"}}let K=W.result;if(!K?.final)continue;w.cancel().catch(()=>{});let U=K.status,G=U?.state??"unknown",V=(U?.message?.parts??[]).filter((J)=>J.kind==="text"&&typeof J.text==="string").map((J)=>J.text).join(`
|
|
5731
5731
|
`)||"No response text";return{success:!0,data:{state:G,response:V}}}X=await my1(w,Q)}return{success:!1,error:"Stream ended without a terminal event"}}class Dr extends Error{timeoutMs;constructor(A){super(`request timed out after ${A}ms`);this.timeoutMs=A,this.name="A2ARequestTimeoutError"}}class qr extends Error{timeoutMs;constructor(A){super(`A2A stream stalled waiting for final event after ${A}ms`);this.timeoutMs=A,this.name="A2AStreamIdleTimeoutError"}}async function neQ(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 Dr($))},$)})])}catch(Y){if(Y instanceof Dr)throw Y;if(B.signal.aborted)throw new Dr($);throw Y}finally{if(X)clearTimeout(X)}}async function my1(A,Q){let w;try{return await Promise.race([A.read(),new Promise(($,B)=>{w=setTimeout(()=>B(new qr(Q)),Q)})])}catch($){if($ instanceof qr)A.cancel().catch(()=>{});throw $}finally{if(w)clearTimeout(w)}}function reQ(A){if(A instanceof Dr||A instanceof qr)return!1;return A instanceof Error}function Ai0(A,Q){let w=Q>1?` after ${Q} attempts`:"";if(A instanceof qr)return`${A.message}${w}`;let $=A instanceof Error?A.message:"Unknown network error";return`Failed to reach remote agent${w}: ${$}`}async function Qi0(A,Q={},w={}){let $=Q.fetch??globalThis.fetch,B={requestTimeoutMs:Q.requestTimeoutMs??SeQ,streamIdleTimeoutMs:Q.streamIdleTimeoutMs??meQ,maxNetworkAttempts:Q.maxNetworkAttempts??ueQ},X=peQ(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:u5("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(!ieQ(Y))return{success:!1,error:`Agent ${A.agent} is not an exact domain-like id and is not saved. Connect or clarify the agent first.`,code:"agent_not_saved"};let U=`https://${Y}`,G=await Ty1(U,$);if(!G)return{success:!1,error:`Could not verify an A2A Agent Card for ${Y}. Connect/save it first if you want to add it to the directory.`,code:"agent_card_unavailable"};let q=Ey1(G.url,Y);if(!q.ok)return{success:!1,error:q.error};let V=await Sy1(G.url,A.message,$,Q.requestSigner,B);if("success"in V&&V.success===!0){let J=typeof V.data==="object"&&V.data!==null?V.data:{};return{...V,data:{...J,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 H=`https://${Y}`,W=await Ty1(H,$);if(!W)return{success:!1,error:`Could not fetch Agent Card from ${H}`};let K=Ey1(W.url,Y);if(!K.ok)return{success:!1,error:K.error};return Sy1(W.url,A.message,$,Q.requestSigner,B)}function cy1(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:ceQ,visibility:"trusted",sideEffects:"external",handler:async(Q)=>{let w=leQ.safeParse(Q);if(!w.success)return{success:!1,error:`Invalid input: ${w.error.message}`};return Qi0(w.data,A)}}}fA();C0();var oeQ=f.object({agent:f.string().trim().min(1).max(253),instruction:f.string().trim().min(1).max(2000),selection:f.string().min(1).max(8000)});function ly1(A,Q){A.messaging.subscribe("a2a:call:request",async(w)=>{let $=oeQ.safeParse(w.payload);if(!$.success)return{success:!1,error:"Invalid A2A call request"};let{agent:B,instruction:X,selection:Y}=$.data,Z=await Qi0({agent:B,message:["A CMS author is asking about selected markdown.",`Instruction: ${X}`,"","Selected markdown:",Y].join(`
|
|
5732
|
-
`)},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:u5("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 wi0={name:"@brains/a2a",version:"0.2.0-alpha.168",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 aeQ={"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 Ag extends UD{agentCard;taskManager=new ep0;agentService;jwksResolver=new ap0;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",wi0,A,My1)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,ly1(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)=>tu.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=Oy1({character:Q,profile:w,version:wi0.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}`,dI(A)),B=await Ny1({method:A.method,url:$.toString(),headers:A.headers,body:Q},this.jwksResolver);if(B){let X=await A4()?.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(aeQ))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 oy;return A.get("/.well-known/agent-card.json",(Q)=>{if(!this.agentCard)return this.withCors(Q.json({error:"Agent Card not ready"},503));return this.withCors(Q.json(this.agentCard))}),A.get("/a2a",(Q)=>{return this.withCors(Q.json({error:"Use POST with JSON-RPC 2.0 requests.",agentCard:"/.well-known/agent-card.json"},405))}),A.options("/a2a",()=>this.withCors(new Response(null,{status:204}))),A.post("/a2a",async(Q)=>{if(!this.agentService)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32603,message:"Agent service not ready"},id:null},503));let w=await Q.req.text(),$;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=vy1.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=Cy1.safeParse(X.data.params??{});if(!Z.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${Z.error.message}`},id:X.data.id}));let H=yy1(X.data.id,Z.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$.permissionLevel,callerDomain:$.callerDomain});if("error"in H)return this.withCors(Q.json(H));let{stream:W}=H;return this.withCors(new Response(W,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let Y=await hy1(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:"/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=A4();if(!A)return;let Q=A.getIssuer();if(iI(Q)||new URL(Q).protocol!=="https:")return;return async(w)=>{let $=await A.getA2ASigningKey();await _y1(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[cy1(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")}}}}fA();C0();var py1={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 iy1={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 dy1={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 ny1={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 ry1={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 oy1={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 sy1={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 ay1={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 ty1={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 Z0w=f.object({type:f.string()}).catchall(f.unknown()),f0w=f.object({lexicon:f.literal(1),id:f.string(),defs:f.object({main:f.object({type:f.literal("record"),key:f.string().min(1),record:f.object({type:f.literal("object"),required:f.array(f.string()).optional(),properties:f.record(f.string(),Z0w)})})})});function lU(A){return f0w.parse(A)}var m6={"ai.rizom.brain.card":lU(py1),"ai.rizom.brain.deck":lU(iy1),"ai.rizom.brain.link":lU(dy1),"ai.rizom.brain.note":lU(ny1),"ai.rizom.brain.post":lU(ry1),"ai.rizom.brain.project":lU(oy1),"ai.rizom.brain.series":lU(sy1),"ai.rizom.brain.socialPost":lU(ay1),"ai.rizom.brain.topic":lU(ty1)},H0w="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function NV(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:H0w}}var ey1={"ai.rizom.brain.card":NV("@brains/atproto"),"ai.rizom.brain.deck":NV("@brains/decks"),"ai.rizom.brain.link":NV("@brains/link"),"ai.rizom.brain.note":NV("@brains/note"),"ai.rizom.brain.post":NV("@brains/blog"),"ai.rizom.brain.project":NV("@brains/portfolio"),"ai.rizom.brain.series":NV("@brains/series"),"ai.rizom.brain.socialPost":NV("@brains/social-media"),"ai.rizom.brain.topic":NV("@brains/topics")};function Qg(){return Object.values(m6)}function J40(A){if(!(A in m6))return;return m6[A]}function F40(){return Object.entries(ey1).map(([A,Q])=>({id:A,...Q}))}C0();function I40(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var W0w=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function K0w(A){let Q=f.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(($)=>W0w.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 Ag1(A){switch(A.type){case"string":return K0w(A);case"integer":return f.number().int();case"boolean":return f.boolean();case"array":{let Q=A.items?Ag1(A.items):f.unknown(),w=f.array(Q);if(A.maxLength!==void 0)w=w.max(A.maxLength);return w}case"object":return U0w(A);case"blob":return f.custom(I40,{message:"expected blob"});default:return f.unknown()}}function Qg1(A){let Q=new Set(A.required??[]),w={};for(let[$,B]of Object.entries(A.properties??{})){let X=Ag1(B);w[$]=Q.has($)?X:X.optional()}return w}function U0w(A){return f.object(Qg1(A)).passthrough()}function $i0(A,Q,w,$=[]){let B=Object.keys(A).filter((X)=>!Q.has(X));if(B.length===0)return;w.addIssue({code:f.ZodIssueCode.custom,path:$,message:`unrecognized field(s): ${B.join(", ")}`})}function G0w(A,Q){if($i0(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),I40(A.brain))$i0(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(I40(A.anchor))$i0(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function pU(A){let Q=f.object({...Qg1(A.defs.main.record),$type:f.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(G0w):Q}var Bi0={"ai.rizom.brain.card":pU(m6["ai.rizom.brain.card"]),"ai.rizom.brain.deck":pU(m6["ai.rizom.brain.deck"]),"ai.rizom.brain.link":pU(m6["ai.rizom.brain.link"]),"ai.rizom.brain.note":pU(m6["ai.rizom.brain.note"]),"ai.rizom.brain.post":pU(m6["ai.rizom.brain.post"]),"ai.rizom.brain.project":pU(m6["ai.rizom.brain.project"]),"ai.rizom.brain.series":pU(m6["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":pU(m6["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":pU(m6["ai.rizom.brain.topic"])};function D0w(A,Q){let w=A;for(let $ of Q){if(typeof $==="symbol")return;if(Array.isArray(w)){w=w[Number($)];continue}if(!I40(w))return;w=w[String($)]}return w}function q0w(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"&&D0w(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 jV(A,Q){let w=pU(A).safeParse(Q);if(w.success)return;let $=w.error.issues[0];if(!$)throw w.error;throw Error(q0w(A,Q,$))}C0();var zr="atproto:brain-card-discovered",Xi0="atproto:brain-discovered",Yi0="atproto:brain-card-refreshed",z0w=f.custom((A)=>Bi0["ai.rizom.brain.card"].safeParse(A).success),Zi0=f.object({repoDid:f.string().min(1),uri:f.string().min(1),cid:f.string().min(1),record:z0w}).strict(),V0w=f.object({agentId:f.string().min(1),name:f.string().min(1),url:f.string().url(),status:f.enum(["discovered","approved","archived"]),repoDid:f.string().min(1).optional(),brainDid:f.string().min(1).optional(),anchorDid:f.string().min(1).optional(),cardUri:f.string().min(1).optional(),cardCid:f.string().min(1).optional()}).strict();class NB{static instance;projections=new Map;static getInstance(){return this.instance??=new NB,this.instance}static createFresh(){return new NB}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}`)}}C0();var wg1={name:"@brains/atproto-registry",version:"0.2.0-alpha.168",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 Bg1=f.object({enabled:f.boolean().default(!0)}),fi0="/atproto/lexicons",F0w=f.strictObject({nsid:f.string(),record:f.record(f.string(),f.unknown())});function $g1(A){return new Response(`${JSON.stringify(A,null,2)}
|
|
5732
|
+
`)},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:u5("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 wi0={name:"@brains/a2a",version:"0.2.0-alpha.169",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 aeQ={"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 Ag extends UD{agentCard;taskManager=new ep0;agentService;jwksResolver=new ap0;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",wi0,A,My1)}async onRegister(A){if(await super.onRegister(A),this.hasWebserver=A.plugins.has("webserver"),this.agentService=A.agent,ly1(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)=>tu.safeParse(Y.metadata)).filter((Y)=>Y.success).map((Y)=>Y.data)}catch{}this.agentCard=Oy1({character:Q,profile:w,version:wi0.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}`,dI(A)),B=await Ny1({method:A.method,url:$.toString(),headers:A.headers,body:Q},this.jwksResolver);if(B){let X=await A4()?.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(aeQ))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 oy;return A.get("/.well-known/agent-card.json",(Q)=>{if(!this.agentCard)return this.withCors(Q.json({error:"Agent Card not ready"},503));return this.withCors(Q.json(this.agentCard))}),A.get("/a2a",(Q)=>{return this.withCors(Q.json({error:"Use POST with JSON-RPC 2.0 requests.",agentCard:"/.well-known/agent-card.json"},405))}),A.options("/a2a",()=>this.withCors(new Response(null,{status:204}))),A.post("/a2a",async(Q)=>{if(!this.agentService)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32603,message:"Agent service not ready"},id:null},503));let w=await Q.req.text(),$;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=vy1.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=Cy1.safeParse(X.data.params??{});if(!Z.success)return this.withCors(Q.json({jsonrpc:"2.0",error:{code:-32602,message:`Invalid params: ${Z.error.message}`},id:X.data.id}));let H=yy1(X.data.id,Z.data.message,{taskManager:this.taskManager,agentService:this.agentService,callerPermissionLevel:$.permissionLevel,callerDomain:$.callerDomain});if("error"in H)return this.withCors(Q.json(H));let{stream:W}=H;return this.withCors(new Response(W,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}}))}let Y=await hy1(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:"/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=A4();if(!A)return;let Q=A.getIssuer();if(iI(Q)||new URL(Q).protocol!=="https:")return;return async(w)=>{let $=await A.getA2ASigningKey();await _y1(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[cy1(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")}}}}fA();C0();var py1={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 iy1={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 dy1={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 ny1={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 ry1={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 oy1={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 sy1={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 ay1={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 ty1={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 Z0w=f.object({type:f.string()}).catchall(f.unknown()),f0w=f.object({lexicon:f.literal(1),id:f.string(),defs:f.object({main:f.object({type:f.literal("record"),key:f.string().min(1),record:f.object({type:f.literal("object"),required:f.array(f.string()).optional(),properties:f.record(f.string(),Z0w)})})})});function lU(A){return f0w.parse(A)}var m6={"ai.rizom.brain.card":lU(py1),"ai.rizom.brain.deck":lU(iy1),"ai.rizom.brain.link":lU(dy1),"ai.rizom.brain.note":lU(ny1),"ai.rizom.brain.post":lU(ry1),"ai.rizom.brain.project":lU(oy1),"ai.rizom.brain.series":lU(sy1),"ai.rizom.brain.socialPost":lU(ay1),"ai.rizom.brain.topic":lU(ty1)},H0w="Additive optional fields are compatible; required-field, type, or constraint changes require a migration plan or new NSID.";function NV(A){return{status:"approved",version:"1.0.0",revision:1,owner:"Rizom",steward:"Rizom protocol registry",projectionPackage:A,compatibility:H0w}}var ey1={"ai.rizom.brain.card":NV("@brains/atproto"),"ai.rizom.brain.deck":NV("@brains/decks"),"ai.rizom.brain.link":NV("@brains/link"),"ai.rizom.brain.note":NV("@brains/note"),"ai.rizom.brain.post":NV("@brains/blog"),"ai.rizom.brain.project":NV("@brains/portfolio"),"ai.rizom.brain.series":NV("@brains/series"),"ai.rizom.brain.socialPost":NV("@brains/social-media"),"ai.rizom.brain.topic":NV("@brains/topics")};function Qg(){return Object.values(m6)}function J40(A){if(!(A in m6))return;return m6[A]}function F40(){return Object.entries(ey1).map(([A,Q])=>({id:A,...Q}))}C0();function I40(A){return typeof A==="object"&&A!==null&&!Array.isArray(A)}var W0w=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;function K0w(A){let Q=f.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(($)=>W0w.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 Ag1(A){switch(A.type){case"string":return K0w(A);case"integer":return f.number().int();case"boolean":return f.boolean();case"array":{let Q=A.items?Ag1(A.items):f.unknown(),w=f.array(Q);if(A.maxLength!==void 0)w=w.max(A.maxLength);return w}case"object":return U0w(A);case"blob":return f.custom(I40,{message:"expected blob"});default:return f.unknown()}}function Qg1(A){let Q=new Set(A.required??[]),w={};for(let[$,B]of Object.entries(A.properties??{})){let X=Ag1(B);w[$]=Q.has($)?X:X.optional()}return w}function U0w(A){return f.object(Qg1(A)).passthrough()}function $i0(A,Q,w,$=[]){let B=Object.keys(A).filter((X)=>!Q.has(X));if(B.length===0)return;w.addIssue({code:f.ZodIssueCode.custom,path:$,message:`unrecognized field(s): ${B.join(", ")}`})}function G0w(A,Q){if($i0(A,new Set(["$type","siteUrl","brain","anchor","skills","model","version","createdAt","updatedAt"]),Q),I40(A.brain))$i0(A.brain,new Set(["did","name","role","purpose","values"]),Q,["brain"]);if(I40(A.anchor))$i0(A.anchor,new Set(["did","name","kind"]),Q,["anchor"])}function pU(A){let Q=f.object({...Qg1(A.defs.main.record),$type:f.literal(A.id).optional()}).passthrough();return A.id==="ai.rizom.brain.card"?Q.superRefine(G0w):Q}var Bi0={"ai.rizom.brain.card":pU(m6["ai.rizom.brain.card"]),"ai.rizom.brain.deck":pU(m6["ai.rizom.brain.deck"]),"ai.rizom.brain.link":pU(m6["ai.rizom.brain.link"]),"ai.rizom.brain.note":pU(m6["ai.rizom.brain.note"]),"ai.rizom.brain.post":pU(m6["ai.rizom.brain.post"]),"ai.rizom.brain.project":pU(m6["ai.rizom.brain.project"]),"ai.rizom.brain.series":pU(m6["ai.rizom.brain.series"]),"ai.rizom.brain.socialPost":pU(m6["ai.rizom.brain.socialPost"]),"ai.rizom.brain.topic":pU(m6["ai.rizom.brain.topic"])};function D0w(A,Q){let w=A;for(let $ of Q){if(typeof $==="symbol")return;if(Array.isArray(w)){w=w[Number($)];continue}if(!I40(w))return;w=w[String($)]}return w}function q0w(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"&&D0w(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 jV(A,Q){let w=pU(A).safeParse(Q);if(w.success)return;let $=w.error.issues[0];if(!$)throw w.error;throw Error(q0w(A,Q,$))}C0();var zr="atproto:brain-card-discovered",Xi0="atproto:brain-discovered",Yi0="atproto:brain-card-refreshed",z0w=f.custom((A)=>Bi0["ai.rizom.brain.card"].safeParse(A).success),Zi0=f.object({repoDid:f.string().min(1),uri:f.string().min(1),cid:f.string().min(1),record:z0w}).strict(),V0w=f.object({agentId:f.string().min(1),name:f.string().min(1),url:f.string().url(),status:f.enum(["discovered","approved","archived"]),repoDid:f.string().min(1).optional(),brainDid:f.string().min(1).optional(),anchorDid:f.string().min(1).optional(),cardUri:f.string().min(1).optional(),cardCid:f.string().min(1).optional()}).strict();class NB{static instance;projections=new Map;static getInstance(){return this.instance??=new NB,this.instance}static createFresh(){return new NB}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}`)}}C0();var wg1={name:"@brains/atproto-registry",version:"0.2.0-alpha.169",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 Bg1=f.object({enabled:f.boolean().default(!0)}),fi0="/atproto/lexicons",F0w=f.strictObject({nsid:f.string(),record:f.record(f.string(),f.unknown())});function $g1(A){return new Response(`${JSON.stringify(A,null,2)}
|
|
5733
5733
|
`,{headers:{"Content-Type":"application/json"}})}class Hi0 extends Uw{constructor(A={}){super("atproto-registry",wg1,A,Bg1)}getWebRoutes(){if(!this.config.enabled)return[];return[{path:`${fi0}/index.json`,method:"GET",public:!0,handler:()=>$g1(this.getIndex())},...Qg().map((A)=>({path:`${fi0}/${A.id}.json`,method:"GET",public:!0,handler:()=>$g1(A)}))]}getIndex(){return{lexicons:F40().map((A)=>({...A,path:`${fi0}/${A.id}.json`}))}}getLexicon(A){return J40(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:f.string().describe("Canonical lexicon NSID"),record:f.record(f.string(),f.unknown()).describe("Record payload to validate")},handler:async(A)=>{let Q=F0w.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 jV(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:Qg().length,nsids:Qg().map((A)=>A.id),metadata:F40()}})}}}function Vr(A={}){return new Hi0(A)}fA();class Wi0{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),H=await w({type:"directory-delete",data:{entityId:Z,entityType:Y,filePath:X}});this.logger.info("Queued delete job for removed file",{jobId:H,path:X,entityId:Z,entityType:Y})}catch(Y){this.logger.warn("Could not extract entity info from deleted file",{path:X,error:Y})}};else this.handleImport=async(X)=>{await Q([X])},this.handleDelete=async(X)=>{this.logger.warn("File deleted but no job queue available",{path:X})}}async handleFileChange(A,Q){this.logger.debug("Processing file change",{event:A,path:Q});try{switch(A){case"add":case"change":await this.handleImport(Q);break;case"delete":case"unlink":await this.handleDelete(Q);break;default:this.logger.debug("Unhandled file event",{event:A,path:Q})}}catch(w){this.logger.error("Failed to handle file change",{event:A,path:Q,error:w})}}}import{EventEmitter as o0w}from"events";import{stat as s0w,Stats as gt$}from"fs";import{readdir as a0w,stat as t0w}from"fs/promises";import*as J6 from"path";import{lstat as Xg1,readdir as I0w,realpath as b0w,stat as L0w}from"fs/promises";import{join as k0w,relative as _0w,resolve as Yg1,sep as N0w}from"path";import{Readable as j0w}from"stream";var sf={FILE_TYPE:"files",DIR_TYPE:"directories",FILE_DIR_TYPE:"files_directories",EVERYTHING_TYPE:"all"},Ki0={root:".",fileFilter:(A)=>!0,directoryFilter:(A)=>!0,type:sf.FILE_TYPE,lstat:!1,depth:2147483648,alwaysStat:!1,highWaterMark:4096};Object.freeze(Ki0);var Wg1="READDIRP_RECURSIVE_ERROR",P0w=new Set(["ENOENT","EPERM","EACCES","ELOOP",Wg1]),Zg1=[sf.DIR_TYPE,sf.EVERYTHING_TYPE,sf.FILE_DIR_TYPE,sf.FILE_TYPE],M0w=new Set([sf.DIR_TYPE,sf.EVERYTHING_TYPE,sf.FILE_DIR_TYPE]),O0w=new Set([sf.EVERYTHING_TYPE,sf.FILE_DIR_TYPE,sf.FILE_TYPE]),x0w=(A)=>P0w.has(A.code),R0w=process.platform==="win32",fg1=(A)=>!0,Hg1=(A)=>{if(A===void 0)return fg1;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 fg1};class Ui0 extends j0w{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={...Ki0,...A},{root:w,type:$}=Q;this._fileFilter=Hg1(Q.fileFilter),this._directoryFilter=Hg1(Q.directoryFilter);let B=Q.lstat?Xg1:L0w;if(R0w)this._stat=(X)=>B(X,{bigint:!0});else this._stat=B;this._maxDepth=Q.depth!=null&&Number.isSafeInteger(Q.depth)?Q.depth:Ki0.depth,this._wantsDir=$?M0w.has($):!1,this._wantsFile=$?O0w.has($):!1,this._wantsEverything=$===sf.EVERYTHING_TYPE,this._root=Yg1(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 H=await this._getEntryType(Z);if(H==="directory"&&this._directoryFilter(Z)){if(B<=this._maxDepth)this.parents.push(this._exploreDir(Z.fullPath,B+1));if(this._wantsDir)this.push(Z),A--}else if((H==="file"||this._includeAsFile(Z))&&this._fileFilter(Z)){if(this._wantsFile)this.push(Z),A--}}}else{let $=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 I0w(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=Yg1(k0w(Q,$));w={path:_0w(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(x0w(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 b0w(w),B=await Xg1($);if(B.isFile())return"file";if(B.isDirectory()){let X=$.length;if(w.startsWith($)&&w.substr(X,1)===N0w){let Y=Error(`Circular symlink detected: "${w}" points to "${$}"`);return Y.code=Wg1,this._onError(Y)}return"directory"}}catch($){return this._onError($),""}}}_includeAsFile(A){let Q=A&&A[this._statsProp];return Q&&this._wantsEverything&&!Q.isDirectory()}}function Kg1(A,Q={}){let w=Q.entryType||Q.type;if(w==="both")w=sf.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&&!Zg1.includes(w))throw Error(`readdirp: Invalid type passed. Use one of ${Zg1.join(", ")}`);return Q.root=A,new Ui0(Q)}import{watch as v0w,unwatchFile as Ug1,watchFile as h0w}from"fs";import{realpath as Gi0,lstat as C0w,open as y0w,stat as Dg1}from"fs/promises";import{type as g0w}from"os";import*as QB from"path";var E0w="data",zi0="end",qg1="close",_40=()=>{};var N40=process.platform,Vi0=N40==="win32",T0w=N40==="darwin",S0w=N40==="linux",m0w=N40==="freebsd",zg1=g0w()==="OS400",R8={ALL:"all",READY:"ready",ADD:"add",CHANGE:"change",ADD_DIR:"addDir",UNLINK:"unlink",UNLINK_DIR:"unlinkDir",RAW:"raw",ERROR:"error"},iU=R8,u0w="watch",c0w={lstat:C0w,stat:Dg1},UP="listeners",b40="errHandlers",wg="rawEmitters",l0w=[UP,b40,wg],p0w=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"]),i0w=(A)=>p0w.has(QB.extname(A).slice(1).toLowerCase()),qi0=(A,Q)=>{if(A instanceof Set)A.forEach(Q);else Q(A)},Jr=(A,Q,w)=>{let $=A[Q];if(!($ instanceof Set))A[Q]=$=new Set([$]);$.add(w)},d0w=(A)=>(Q)=>{let w=A[Q];if(w instanceof Set)w.clear();else delete A[Q]},Fr=(A,Q,w)=>{let $=A[Q];if($ instanceof Set)$.delete(w);else if($===w)delete A[Q]},Vg1=(A)=>A instanceof Set?A.size===0:!A,L40=new Map;function Gg1(A,Q,w,$,B){let X=(Y,Z)=>{if(w(A),B(Y,Z,{watchedPath:A}),Z&&A!==Z)k40(QB.resolve(A,Z),UP,QB.join(A,Z))};try{return v0w(A,{persistent:Q.persistent},X)}catch(Y){$(Y);return}}var k40=(A,Q,w,$,B)=>{let X=L40.get(A);if(!X)return;qi0(X[Q],(Y)=>{Y(w,$,B)})},n0w=(A,Q,w,$)=>{let{listener:B,errHandler:X,rawEmitter:Y}=$,Z=L40.get(Q),H;if(!w.persistent){if(H=Gg1(A,w,B,X,Y),!H)return;return H.close.bind(H)}if(Z)Jr(Z,UP,B),Jr(Z,b40,X),Jr(Z,wg,Y);else{if(H=Gg1(A,w,k40.bind(null,Q,UP),X,k40.bind(null,Q,wg)),!H)return;H.on(iU.ERROR,async(W)=>{let K=k40.bind(null,Q,b40);if(Z)Z.watcherUnusable=!0;if(Vi0&&W.code==="EPERM")try{await(await y0w(A,"r")).close(),K(W)}catch(U){}else K(W)}),Z={listeners:B,errHandlers:X,rawEmitters:Y,watcher:H},L40.set(Q,Z)}return()=>{if(Fr(Z,UP,B),Fr(Z,b40,X),Fr(Z,wg,Y),Vg1(Z.listeners))Z.watcher.close(),L40.delete(Q),l0w.forEach(d0w(Z)),Z.watcher=void 0,Object.freeze(Z)}},Di0=new Map,r0w=(A,Q,w,$)=>{let{listener:B,rawEmitter:X}=$,Y=Di0.get(Q),Z=Y&&Y.options;if(Z&&(Z.persistent<w.persistent||Z.interval>w.interval))Ug1(Q),Y=void 0;if(Y)Jr(Y,UP,B),Jr(Y,wg,X);else Y={listeners:B,rawEmitters:X,options:w,watcher:h0w(Q,w,(H,W)=>{qi0(Y.rawEmitters,(U)=>{U(iU.CHANGE,Q,{curr:H,prev:W})});let K=H.mtimeMs;if(H.size!==W.size||K>W.mtimeMs||K===0)qi0(Y.listeners,(U)=>U(A,H))})},Di0.set(Q,Y);return()=>{if(Fr(Y,UP,B),Fr(Y,wg,X),Vg1(Y.listeners))Di0.delete(Q),Ug1(Q),Y.options=Y.watcher=void 0,Object.freeze(Y)}};class Ji0{fsw;_boundHandleError;constructor(A){this.fsw=A,this._boundHandleError=(Q)=>A._handleError(Q)}_watchWithNodeFs(A,Q){let w=this.fsw.options,$=QB.dirname(A),B=QB.basename(A);this.fsw._getWatchedDir($).add(B);let Y=QB.resolve(A),Z={persistent:w.persistent};if(!Q)Q=_40;let H;if(w.usePolling){let W=w.interval!==w.binaryInterval;Z.interval=W&&i0w(B)?w.binaryInterval:w.interval,H=r0w(A,Y,Z,{listener:Q,rawEmitter:this.fsw._emitRaw})}else H=n0w(A,Y,Z,{listener:Q,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw});return H}_handleFile(A,Q,w){if(this.fsw.closed)return;let $=QB.dirname(A),B=QB.basename(A),X=this.fsw._getWatchedDir($),Y=Q;if(X.has(B))return;let Z=async(W,K)=>{if(!this.fsw._throttle(u0w,A,5))return;if(!K||K.mtimeMs===0)try{let U=await Dg1(A);if(this.fsw.closed)return;let{atimeMs:G,mtimeMs:q}=U;if(!G||G<=q||q!==Y.mtimeMs)this.fsw._emit(iU.CHANGE,A,U);if((T0w||S0w||m0w)&&Y.ino!==U.ino){this.fsw._closeFile(W),Y=U;let V=this._watchWithNodeFs(A,Z);if(V)this.fsw._addPathCloser(W,V)}else Y=U}catch(U){this.fsw._remove($,B)}else if(X.has(B)){let{atimeMs:U,mtimeMs:G}=K;if(!U||U<=G||G!==Y.mtimeMs)this.fsw._emit(iU.CHANGE,A,K);Y=K}},H=this._watchWithNodeFs(A,Z);if(!(w&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(A)){if(!this.fsw._throttle(iU.ADD,A,0))return;this.fsw._emit(iU.ADD,A,Q)}return H}async _handleSymlink(A,Q,w,$){if(this.fsw.closed)return;let B=A.fullPath,X=this.fsw._getWatchedDir(Q);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let Y;try{Y=await Gi0(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(iU.CHANGE,w,A.stats)}else X.add($),this.fsw._symlinkPaths.set(B,Y),this.fsw._emit(iU.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=QB.join(A,"");let Z=$?`${A}:${$}`:A;if(Y=this.fsw._throttle("readdir",Z,1000),!Y)return;let H=this.fsw._getWatchedDir(w.path),W=new Set,K=this.fsw._readdirp(A,{fileFilter:(U)=>w.filterPath(U),directoryFilter:(U)=>w.filterDir(U)});if(!K)return;return K.on(E0w,async(U)=>{if(this.fsw.closed){K=void 0;return}let G=U.path,q=QB.join(A,G);if(W.add(G),U.stats.isSymbolicLink()&&await this._handleSymlink(U,A,q,G))return;if(this.fsw.closed){K=void 0;return}if(G===$||!$&&!H.has(G))this.fsw._incrReadyCount(),q=QB.join(B,QB.relative(B,q)),this._addToNodeFs(q,Q,w,X+1)}).on(iU.ERROR,this._boundHandleError),new Promise((U,G)=>{if(!K)return G();K.once(zi0,()=>{if(this.fsw.closed){K=void 0;return}let q=Y?Y.clear():!1;if(U(void 0),H.getChildren().filter((V)=>{return V!==A&&!W.has(V)}).forEach((V)=>{this.fsw._remove(A,V)}),K=void 0,q)this._handleRead(A,!1,w,$,B,X,Y)})})}async _handleDir(A,Q,w,$,B,X,Y){let Z=this.fsw._getWatchedDir(QB.dirname(A)),H=Z.has(QB.basename(A));if(!(w&&this.fsw.options.ignoreInitial)&&!B&&!H)this.fsw._emit(iU.ADD_DIR,A,Q);Z.add(QB.basename(A)),this.fsw._getWatchedDir(A);let W,K,U=this.fsw.options.depth;if((U==null||$<=U)&&!this.fsw._symlinkPaths.has(Y)){if(!B){if(await this._handleRead(A,w,X,B,A,$,W),this.fsw.closed)return}K=this._watchWithNodeFs(A,(G,q)=>{if(q&&q.mtimeMs===0)return;this._handleRead(G,!1,X,B,A,$,W)})}return K}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 c0w[Y.statMethod](Y.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(Y.watchPath,Z))return X(),!1;let H=this.fsw.options.followSymlinks,W;if(Z.isDirectory()){let K=QB.resolve(A),U=H?await Gi0(A):A;if(this.fsw.closed)return;if(W=await this._handleDir(Y.watchPath,Z,Q,$,B,Y,U),this.fsw.closed)return;if(K!==U&&U!==void 0)this.fsw._symlinkPaths.set(K,U)}else if(Z.isSymbolicLink()){let K=H?await Gi0(A):A;if(this.fsw.closed)return;let U=QB.dirname(Y.watchPath);if(this.fsw._getWatchedDir(U).add(Y.watchPath),this.fsw._emit(iU.ADD,Y.watchPath,Z),W=await this._handleDir(U,Z,Q,$,A,Y,K),this.fsw.closed)return;if(K!==void 0)this.fsw._symlinkPaths.set(QB.resolve(A),K)}else W=this._handleFile(Y.watchPath,Z,Q);if(X(),W)this.fsw._addPathCloser(A,W);return!1}catch(Z){if(this.fsw._handleError(Z))return X(),A}}}/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */var Fi0="/",e0w="//",Lg1=".",AAw="..",QAw="string",wAw=/\\/g,kg1=/\/\//g,$Aw=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,BAw=/^\.[/\\]/;function j40(A){return Array.isArray(A)?A:[A]}var Ii0=(A)=>typeof A==="object"&&A!==null&&!(A instanceof RegExp);function XAw(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=J6.relative(A.path,Q);if(!w)return!1;return!w.startsWith("..")&&!J6.isAbsolute(w)}return!1};return()=>!1}function YAw(A){if(typeof A!=="string")throw Error("string expected");A=J6.normalize(A),A=A.replace(/\\/g,"/");let Q=!1;if(A.startsWith("//"))Q=!0;if(A=A.replace(kg1,"/"),Q)A="/"+A;return A}function Jg1(A,Q,w){let $=YAw(Q);for(let B=0;B<A.length;B++){let X=A[B];if(X($,w))return!0}return!1}function ZAw(A,Q){if(A==null)throw TypeError("anymatch: specify first argument");let $=j40(A).map((B)=>XAw(B));if(Q==null)return(B,X)=>{return Jg1($,B,X)};return Jg1($,Q)}var Fg1=(A)=>{let Q=j40(A).flat();if(!Q.every((w)=>typeof w===QAw))throw TypeError(`Non-string provided as watch path: ${Q}`);return Q.map(_g1)},Ig1=(A)=>{let Q=A.replace(wAw,Fi0),w=!1;if(Q.startsWith(e0w))w=!0;if(Q=Q.replace(kg1,Fi0),w)Q=Fi0+Q;return Q},_g1=(A)=>Ig1(J6.normalize(Ig1(A))),bg1=(A="")=>(Q)=>{if(typeof Q==="string")return _g1(J6.isAbsolute(Q)?Q:J6.join(A,Q));else return Q},fAw=(A,Q)=>{if(J6.isAbsolute(A))return A;return J6.join(Q,A)},HAw=Object.freeze(new Set);class Ng1{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!==Lg1&&A!==AAw)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 a0w(w)}catch($){if(this._removeWatcher)this._removeWatcher(J6.dirname(w),J6.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=_40,this.items=HAw,Object.freeze(this)}}var WAw="stat",KAw="lstat";class jg1{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(A,Q,w){this.fsw=w;let $=A;this.path=A=A.replace(BAw,""),this.watchPath=$,this.fullWatchPath=J6.resolve($),this.dirParts=[],this.dirParts.forEach((B)=>{if(B.length>1)B.pop()}),this.followSymlinks=Q,this.statMethod=Q?WAw:KAw}entryPath(A){return J6.join(this.watchPath,J6.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 bi0 extends o0w{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?j40(A.ignored):j40([]),awaitWriteFinish:Q===!0?w:typeof Q==="object"?{...w,...Q}:!1};if(zg1)$.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=_40,this._readyEmitted=!0,process.nextTick(()=>this.emit(R8.READY))},this._emitRaw=(...Z)=>this.emit(R8.RAW,...Z),this._boundRemove=this._remove.bind(this),this.options=$,this._nodeFsHandler=new Ji0(this),Object.freeze($)}_addIgnoredPath(A){if(Ii0(A)){for(let Q of this._ignoredPaths)if(Ii0(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(Ii0(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=Fg1(A);if($)B=B.map((X)=>{return fAw(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(J6.dirname(Y),J6.basename(Q||Y))})}),this}unwatch(A){if(this.closed)return this;let Q=Fg1(A),{cwd:w}=this.options;return Q.forEach(($)=>{if(!J6.isAbsolute($)&&!this._closers.has($)){if(w)$=J6.join(w,$);$=J6.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?J6.relative(this.options.cwd,w):w)||Lg1;A[B]=Q.getChildren().sort()}),A}emitWithAll(A,Q){if(this.emit(A,...Q),A!==R8.ERROR)this.emit(R8.ALL,A,...Q)}async _emit(A,Q,w){if(this.closed)return;let $=this.options;if(Vi0)Q=J6.normalize(Q);if($.cwd)Q=J6.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===R8.UNLINK)return this._pendingUnlinks.set(Q,[A,...B]),setTimeout(()=>{this._pendingUnlinks.forEach((Z,H)=>{this.emit(...Z),this.emit(R8.ALL,...Z),this._pendingUnlinks.delete(H)})},typeof $.atomic==="number"?$.atomic:100),this;if(A===R8.ADD&&this._pendingUnlinks.has(Q))A=R8.CHANGE,this._pendingUnlinks.delete(Q)}if(X&&(A===R8.ADD||A===R8.CHANGE)&&this._readyEmitted){let Z=(H,W)=>{if(H)A=R8.ERROR,B[0]=H,this.emitWithAll(A,B);else if(W){if(B.length>1)B[1]=W;else B.push(W);this.emitWithAll(A,B)}};return this._awaitWriteFinish(Q,X.stabilityThreshold,A,Z),this}if(A===R8.CHANGE){if(!this._throttle(R8.CHANGE,Q,50))return this}if($.alwaysStat&&w===void 0&&(A===R8.ADD||A===R8.ADD_DIR||A===R8.CHANGE)){let Z=$.cwd?J6.join($.cwd,Q):Q,H;try{H=await t0w(Z)}catch(W){}if(!H||this.closed)return;B.push(H)}return this.emitWithAll(A,B),this}_handleError(A){let Q=A&&A.code;if(A&&Q!=="ENOENT"&&Q!=="ENOTDIR"&&(!this.options.ignorePermissionErrors||Q!=="EPERM"&&Q!=="EACCES"))this.emit(R8.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 H=$.get(Q),W=H?H.count:0;if($.delete(Q),clearTimeout(X),H)clearTimeout(H.timeoutObject);return W};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&&!J6.isAbsolute(A))Z=J6.join(this.options.cwd,A);let H=new Date,W=this._pendingWrites;function K(U){s0w(Z,(G,q)=>{if(G||!W.has(A)){if(G&&G.code!=="ENOENT")$(G);return}let V=Number(new Date);if(U&&q.size!==U.size)W.get(A).lastChange=V;let J=W.get(A);if(V-J.lastChange>=Q)W.delete(A),$(void 0,q);else Y=setTimeout(K,X,q)})}if(!W.has(A))W.set(A,{lastChange:H,cancelWait:()=>{return W.delete(A),clearTimeout(Y),w}}),Y=setTimeout(K,X)}_isIgnored(A,Q){if(this.options.atomic&&$Aw.test(A))return!0;if(!this._userIgnored){let{cwd:w}=this.options,B=(this.options.ignored||[]).map(bg1(w)),Y=[...[...this._ignoredPaths].map(bg1(w)),...B];this._userIgnored=ZAw(Y,void 0)}return this._userIgnored(A,Q)}_isntIgnored(A,Q){return!this._isIgnored(A,Q)}_getWatchHelpers(A){return new jg1(A,this.options.followSymlinks,this)}_getWatchedDir(A){let Q=J6.resolve(A);if(!this._watched.has(Q))this._watched.set(Q,new Ng1(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 $=J6.join(A,Q),B=J6.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((U)=>this._remove($,U));let Z=this._getWatchedDir(A),H=Z.has(Q);if(Z.remove(Q),this._symlinkPaths.has(B))this._symlinkPaths.delete(B);let W=$;if(this.options.cwd)W=J6.relative(this.options.cwd,$);if(this.options.awaitWriteFinish&&this._pendingWrites.has(W)){if(this._pendingWrites.get(W).cancelWait()===R8.ADD)return}this._watched.delete($),this._watched.delete(B);let K=w?R8.UNLINK_DIR:R8.UNLINK;if(H&&!this._isIgnored($))this._emit(K,$);this._closePath($)}_closePath(A){this._closeFile(A);let Q=J6.dirname(A);this._getWatchedDir(Q).remove(J6.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:R8.ALL,alwaysStat:!0,lstat:!0,...Q,depth:0},$=Kg1(A,w);return this._streams.add($),$.once(qg1,()=>{$=void 0}),$.once(zi0,()=>{if($)this._streams.delete($),$=void 0}),$}}function UAw(A,Q={}){let w=new bi0(Q);return w.add(A),w}var Pg1={watch:UAw,FSWatcher:bi0};import{extname as GAw}from"path";var P40=[".png",".jpg",".jpeg",".webp",".gif",".svg"];function GP(A){let Q=GAw(A).toLowerCase();return P40.includes(Q)}function Mg1(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 Li0(A){switch(A.toLowerCase()){case"jpeg":return".jpg";case"svg+xml":return".svg";default:return`.${A.toLowerCase()}`}}import{isAbsolute as DAw,relative as qAw,sep as Og1,join as zAw}from"path";function sW(A,Q){return DAw(Q)?Q:zAw(A,Q)}function $g(A,Q){let w=sW(A,Q),$=qAw(A,w);return Og1==="/"?$:$.split(Og1).join("/")}function VAw(A,Q){if(!$g(Q,A).startsWith("image/"))return!1;return GP(A)}function JAw(A,Q){if($g(Q,A).split("/")[0]?.startsWith("_"))return!1;if(A.endsWith(".md"))return!0;return VAw(A,Q)}class ki0{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=Pg1.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(!JAw(Q,this.syncPath))return;this.logger.debug("File change detected",{event:A,path:Q});let w=$g(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 $=sW(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 xg1(A,Q){if(A?.isWatching())return Q.logger.debug("Already watching directory"),A;return FAw(Q)}function Rg1(A){if(A)A.stop();return}function vg1(A,Q){if(A)A.setCallback(Q)}async function FAw(A){let{logger:Q,syncPath:w,watchInterval:$,importEntities:B,jobQueueCallback:X,fileOperations:Y,deleteOnFileRemoval:Z}=A,H=new Wi0(Q,B,X,Y,Z),W=new ki0({syncPath:w,watchInterval:$,logger:Q,onFileChange:async(K,U)=>{await H.handleFileChange(K,U)}});return await W.start(),W}async function hg1(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}}fA();class _i0{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??g4(),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 Ni0{syncInProgress=!1;logger;fileOperations;batchOperationsManager;constructor(A){this.logger=A.logger,this.fileOperations=A.fileOperations,this.batchOperationsManager=new _i0({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 ji0{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 NAw,dirname as jAw,extname as PAw}from"path";import{extname as IAw}from"path";var M40=[".pdf"],Cg1=".meta.json";function DP(A){let Q=IAw(A).toLowerCase();return M40.includes(Q)}function yg1(A){return A.toLowerCase().endsWith(Cg1)}function Pi0(A){return`${A}${Cg1}`}function gg1(A){switch(A.toLowerCase().replace(".","")){case"pdf":default:return"application/pdf"}}import{extname as bAw,join as O40}from"path";function x40(A,Q){let $=$g(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]=Eg1(Z);Y=X.join(":")}else Y=Eg1(X[0]??"");return{entityType:B,id:Y}}function Tg1(A,Q,w,$=".md"){let B=Q.split(":").filter((W)=>W.length>0),X=w==="note";if(B.length===1)return X?O40(A,`${B[0]}${$}`):O40(A,w,`${B[0]}${$}`);let Y=B;if(B[0]===w)Y=B.slice(1);let Z=Y[Y.length-1],H=Y.slice(0,-1);if(X)return O40(A,...H,`${Z}${$}`);return O40(A,w,...H,`${Z}${$}`)}function Sg1(A){if(A.entityType==="document")return".pdf";if(A.entityType!=="image")return".md";let Q=A.metadata.format;if(Q)return Li0(Q);let w=A.content.match(/^data:image\/([a-z+]+);base64,/i);return w?.[1]?Li0(w[1]):".md"}function Eg1(A){let Q=bAw(A).toLowerCase();return Q===".md"||P40.includes(Q)||M40.includes(Q)?A.slice(0,-Q.length):A}C0();Kf();import{mkdir as MAw,readFile as Bg,writeFile as Oi0,stat as OAw,utimes as xAw}from"fs/promises";import{join as R40}from"path";import{mkdir as mg1,readdir as kAw,stat as _Aw}from"fs/promises";import{access as LAw}from"fs/promises";async function J5(A){try{return await LAw(A),!0}catch{return!1}}async function Mi0(A,Q){return pg1(A,Q,{includeDocuments:!1,includeImages:!1})}async function ug1(A,Q){return pg1(A,Q,{includeDocuments:!0,includeImages:!0})}async function cg1(A,Q){if(!await J5(A))await mg1(A,{recursive:!0});for(let w of Q)if(w!=="note")await mg1(R40(A,w),{recursive:!0})}async function lg1(A,Q){let w=[],$={totalFiles:0,byEntityType:{}};if(!await J5(A))return{files:w,stats:$};let B=await Mi0(A,Q);for(let X of B)try{let Y=R40(A,X),Z=await _Aw(Y),{entityType:H}=x40(A,X);w.push({path:X,entityType:H,modified:Z.mtime}),$.totalFiles++,$.byEntityType[H]=($.byEntityType[H]??0)+1}catch{continue}return{files:w,stats:$}}async function pg1(A,Q,w){let $=[];if(!await J5(A))return $;let B=async(X,Y="",Z=!1,H=!1)=>{let W=await kAw(X,{withFileTypes:!0});for(let K of W){let U=Y?R40(Y,K.name):K.name;if(K.isFile()&&!K.name.endsWith(".invalid")&&!yg1(K.name)){if(K.name.endsWith(".md"))$.push(U);else if(w.includeImages&&Z&&GP(K.name))$.push(U);else if(w.includeDocuments&&H&&DP(K.name))$.push(U)}else if(K.isDirectory()&&!K.name.startsWith(".")){if(Y===""&&!Q.hasEntityType(K.name))continue;let G=R40(X,K.name),q=K.name==="image"&&Y==="",V=K.name==="document"&&Y==="";await B(G,U,Z||q,H||V)}}};return await B(A),$}var RAw=f.record(f.string(),f.unknown());class xi0{syncPath;entityService;constructor(A,Q){this.syncPath=A,this.entityService=Q}parseEntityFromPath(A){return x40(this.syncPath,A)}async readEntity(A){let Q=sW(this.syncPath,A),w=await OAw(Q),{entityType:$,id:B}=this.parseEntityFromPath(A),X=w.birthtime.getTime()>0?w.birthtime:w.mtime,Y=w.mtime,Z,H;if(GP(A)||DP(A)){let U=(await Bg(Q)).toString("base64"),G=PAw(A);if(Z=`data:${DP(A)?gg1(G):Mg1(G)};base64,${U}`,DP(A))H=await this.readDocumentSidecar(Q,A)}else Z=await Bg(Q,"utf-8");let W={entityType:$,id:B,content:Z,created:X,updated:Y};if(H)W.metadata=H;return W}async readDocumentSidecar(A,Q){let w={mimeType:"application/pdf",filename:NAw(Q)},$=Pi0(A);if(!await J5($))return w;try{let B=await Bg($,"utf-8"),X=RAw.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"),H=!1;if(await J5(Q)){let W=await Bg(Q),K=b6(W.toString("base64")),U=b6(Z.toString("base64"));if(K===U)H=!0}if(!H)await this.ensureEntityDirectory(A,Q),await Oi0(Q,Z);if($)await this.writeDocumentSidecar(A,Q);if(H)return}else{let X=this.entityService.serializeEntity(A);if(await J5(Q)){let Y=await Bg(Q,"utf-8"),Z=b6(Y),H=b6(X);if(Z===H)return}await this.ensureEntityDirectory(A,Q),await Oi0(Q,X,"utf-8")}let B=new Date(A.updated);await xAw(Q,B,B)}async ensureEntityDirectory(A,Q){if(A.entityType!=="note")await MAw(jAw(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=Pi0(Q),X=`${JSON.stringify($,null,2)}
|
|
5734
5734
|
`;if(await J5(B)){if(await Bg(B,"utf-8")===X)return}await this.ensureEntityDirectory(A,B),await Oi0(B,X,"utf-8")}getFilePath(A,Q,w=".md"){return Tg1(this.syncPath,A,Q,w)}getEntityFilePath(A){return this.getFilePath(A.id,A.entityType,Sg1(A))}async getAllMarkdownFiles(){return Mi0(this.syncPath,this.entityService)}async getAllSyncFiles(){return ug1(this.syncPath,this.entityService)}async ensureDirectoryStructure(A){await cg1(this.syncPath,A)}shouldUpdateEntity(A,Q){let w=b6(Q.content);return A.contentHash!==w}async gatherFileStatus(){return lg1(this.syncPath,this.entityService)}async syncDirectoryExists(){return J5(this.syncPath)}async fileExists(A){return J5(A)}}r4();C0();K7();k2();r4();async function v40(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}=aF(Y),H=$N(Z),W=tF(Z);if(!H||!W)throw Error("Could not detect image format or dimensions");let K=await Q.createEntity({entity:{id:A.id,entityType:"image",content:Y,metadata:{title:A.title,alt:A.alt,format:H,width:W.width,height:W.height,sourceUrl:B}}});return $.debug("Created image entity from URL",{sourceUrl:B,imageId:K.entityId}),K.entityId}var ig1=f.object({title:f.string(),slug:f.string().optional(),coverImageUrl:f.url(),coverImageId:f.string().optional(),coverImageAlt:f.string().optional()});class Ri0{entityService;fetcher;logger;constructor(A,Q,w=kW){this.entityService=A,this.fetcher=w,this.logger=Q.child("FrontmatterImageConverter")}detectCoverImageUrl(A){let Q;try{Q=p6(A)}catch{return null}let{frontmatter:w}=Q,$=ig1.safeParse(w);if(!$.success)return null;if($.data.coverImageId)return null;let{title:B,slug:X,coverImageUrl:Y,coverImageAlt:Z}=$.data;if(!wN(Y))return null;return{sourceUrl:Y,postTitle:B,postSlug:X??q1(B),customAlt:Z}}async convert(A){let Q;try{Q=p6(A)}catch(W){return this.logger.debug("Parse failed",{error:W}),{content:A,converted:!1}}let{frontmatter:w}=Q,$=ig1.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(!wN(Y))return{content:A,converted:!1};let H={postTitle:B,postSlug:X??q1(B),sourceUrl:Y,customAlt:Z};try{let W=await this.createImageEntity(H),K={...w};return delete K.coverImageUrl,delete K.coverImageAlt,K.coverImageId=W,{content:j_(K,Q.content),converted:!0,imageId:W}}catch(W){return this.logger.warn("Failed to convert coverImageUrl",{url:Y,error:dA(W)}),{content:A,converted:!1}}}async createImageEntity(A){let{postTitle:Q,postSlug:w,sourceUrl:$,customAlt:B}=A,X=`Cover image for ${Q}`;return v40({id:`${w}-cover`,title:X,alt:B??X,sourceUrl:$},this.entityService,this.fetcher,this.logger)}}r4();class Ir{entityService;fetcher;logger;constructor(A,Q,w=kW){this.entityService=A,this.fetcher=w,this.logger=Q.child("MarkdownImageConverter")}detectInlineImages(A,Q){let w=[],$=uM0(A);for(let B of $){if(!wN(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++),H=``;$=$.replace(Y.originalMarkdown,H),B++,this.logger.debug("Converted inline image",{sourceUrl:Y.sourceUrl,imageId:Z})}catch(Z){this.logger.warn("Failed to convert inline image",{sourceUrl:Y.sourceUrl,error:dA(Z)})}return{content:$,converted:B>0,convertedCount:B}}async createImageEntity(A,Q){let{sourceUrl:w,alt:$,postSlug:B}=A;return v40({id:`${B}-inline-${Q}`,title:$||`Inline image ${Q+1} for ${B}`,alt:$||"",sourceUrl:w},this.entityService,this.fetcher,this.logger)}}class vi0{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 H=X.slice(Z,Z+w),W=await $(H);B.imported+=W.imported,B.skipped+=W.skipped,B.failed+=W.failed,B.quarantined+=W.quarantined,B.errors.push(...W.errors),B.quarantinedFiles.push(...W.quarantinedFiles),B.jobIds.push(...W.jobIds);let K=Math.min(Z+w,Y),U=Math.round(K/Y*40);await Q.report({progress:U,message:`Imported ${K}/${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}}fA();import{rename as vAw,appendFile as hAw,readFile as CAw,writeFile as yAw,access as gAw}from"fs/promises";import{join as dg1}from"path";class hi0{logger;syncPath;constructor(A,Q){this.logger=A,this.syncPath=Q}isValidationError(A){return C20(A)}async quarantineInvalidFile(A,Q,w,$){let B=$(A),X=`${B}.invalid`;try{await vAw(B,X),w.quarantined++,w.quarantinedFiles.push(A);let Y=dg1(this.syncPath,".import-errors.log"),Z=new Date().toISOString(),H=dA(Q),W=`${Z} - ${A}: ${H}
|
|
5735
5735
|
\u2192 ${A}.invalid
|
|
@@ -5758,7 +5758,7 @@ ${Ky1}</style></head><body>${Gr(A)}<main id="root" data-web-chat-root>Brain Chat
|
|
|
5758
5758
|
*...and ${A.files.length-10} more files*`)}if(A.exists&&A.stats.totalFiles===0)Q.push(`
|
|
5759
5759
|
## Getting Started
|
|
5760
5760
|
`),Q.push("Your sync directory is empty. Entities will be organized as follows:"),Q.push("- Base entities: `/<entity-id>.md`"),Q.push("- Other types: `/<entity-type>/<entity-id>.md`");return Q.join(`
|
|
5761
|
-
`)}}fA();class $X0 extends z6{directorySync;constructor(A,Q,w){super(A,{schema:yd0,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}}}fA();class BX0 extends z6{directorySync;constructor(A,Q,w){super(A,{schema:Cd0,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}}}fA();class XX0 extends z6{directorySync;context;constructor(A,Q,w){super(A,{schema:vd0,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 H=B==="export"?10:60;await w.report({progress:H,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,w),await w.report({progress:100,message: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 H=(await Promise.all(A.map((K)=>w.getAsyncJobStatus(K)))).filter((K)=>K&&(K.status==="completed"||K.status==="failed")).length;if(H===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-X>$){this.logger.warn(`Timeout waiting for import jobs (${H}/${A.length} completed)`);return}let W=Math.round(H/A.length*100);return await Q.report({progress:50+Math.round(W*0.05),message:`Processing ${H}/${A.length} entities`}),await new Promise((K)=>setTimeout(K,B)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}fA();class YX0 extends z6{context;directorySync;gitSync;constructor(A,Q,w,$){super(A,{schema:hd0,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`}),A6w($)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function A6w(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}fA();class ZX0 extends z6{context;constructor(A,Q,w){super(A,{schema:QX0,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,w){let $=QX0.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}}}fA();C0();var Q6w=f.object({});class fX0 extends z6{directorySync;constructor(A,Q){super(A,{schema:Q6w,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`}),$}}fA();r4();K7();Q$();C0();r4();import{readFile as w6w,writeFile as $6w}from"fs/promises";var B6w=gd0,X6w=f.record(f.string(),f.unknown());class HX0 extends z6{context;fetcher;constructor(A,Q,w=kW){super(Q,{schema:B6w,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:Zw.INIT,message:`Reading file: ${$}`});let H;try{H=await w6w($,"utf-8")}catch(F){return this.logger.error("Failed to read file",{filePath:$,error:dA(F)}),j8.failure(F)}let W;try{W=p6(H)}catch(F){return this.logger.warn("Failed to parse markdown",{filePath:$,error:dA(F)}),j8.failure(F)}let K=X6w.safeParse(W.frontmatter),U=K.success?K.data:{};if(U.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:$}),await this.reportProgress(w,{progress:Zw.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(w,{progress:Zw.FETCH,message:"Checking for existing image"});let G=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:B}},limit:1}}),q;if(G[0])q=G[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:B,imageId:q}),await this.reportProgress(w,{progress:Zw.EXTRACT,message:`Reusing existing image: ${q}`});else{await this.reportProgress(w,{progress:Zw.PROCESS,message:`Fetching image from ${B}`});let F;try{F=await this.fetcher(B)}catch(x){return this.logger.error("Failed to fetch image",{sourceUrl:B,error:dA(x)}),j8.failure(x)}await this.reportProgress(w,{progress:Zw.GENERATE,message:"Creating image entity"});let{base64:k}=aF(F),j=$N(k),_=tF(k);if(!j||!_)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:B}),j8.failure(Error("Could not detect image format or dimensions"));q=`${Y}-cover`;let O=`Cover image for ${X}`,R=Z??O;await this.context.entityService.createEntity({entity:{id:q,entityType:"image",content:F,metadata:{title:O,alt:R,format:j,width:_.width,height:_.height,sourceUrl:B}}}),this.logger.debug("Created image entity",{imageId:q,sourceUrl:B}),await this.reportProgress(w,{progress:Zw.EXTRACT,message:`Created image: ${q}`})}await this.reportProgress(w,{progress:Zw.SAVE,message:"Updating file"});let V={...U};delete V.coverImageUrl,delete V.coverImageAlt,V.coverImageId=q;let J=j_(V,W.content);try{await $6w($,J,"utf-8")}catch(F){return this.logger.error("Failed to write file",{filePath:$,error:dA(F)}),j8.failure(F)}return await this.reportProgress(w,{progress:Zw.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:$,imageId:q,sourceUrl:B}),{success:!0,imageId:q}}catch(H){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:$,error:dA(H)}),j8.failure(H)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}fA();r4();Q$();import{readFile as Y6w,writeFile as Z6w}from"fs/promises";class WX0 extends z6{converter;constructor(A,Q,w=kW){super(Q,{schema:Ed0,jobTypeName:"inline-image-convert"});this.converter=new Ir(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:Zw.INIT,message:`Reading file: ${$}`});let X;try{X=await Y6w($,"utf-8")}catch(H){let W=dA(H);return this.logger.error("Failed to read file",{filePath:$,error:W}),{success:!1,error:W}}await this.reportProgress(w,{progress:Zw.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:Zw.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:Zw.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:Zw.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(w,{progress:Zw.SAVE,message:"Writing updated file"});try{await Z6w($,Z.content,"utf-8")}catch(H){let W=dA(H);return this.logger.error("Failed to write file",{filePath:$,error:W}),{success:!1,error:W}}return await this.reportProgress(w,{progress:Zw.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:$,convertedCount:Z.convertedCount}),{success:!0,convertedCount:Z.convertedCount}}catch(X){let Y=dA(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 xm1(A,Q,w){let $=(B)=>w.child(B);A.jobs.registerHandler("directory-sync",new XX0($("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new $X0($("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new BX0($("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new ZX0($("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new fX0($("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new HX0(A,$("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new WX0(A,$("InlineImageConversionJobHandler"))),w.debug("Registered async job handlers")}fA();C0();import{unlink as f6w,access as H6w}from"fs/promises";var W6w=f.record(f.string(),f.unknown());function Rm1(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(H){w.error("Auto-export FAILED for created entity",{id:Z.id,entityType:Z.entityType,error:H instanceof Error?H.message:String(H),stack:H instanceof Error?H.stack:void 0})}return{success:!0}}),B("entity:updated",async(Y)=>{let{entityType:Z,entityId:H}=Y.payload;try{let W=await X.getEntity({entityType:Z,id:H});if(!W)return w.debug("Entity not found in DB, skipping export",{entityType:Z,entityId:H}),{success:!1};await Q.fileOps.writeEntity(W),w.debug("Auto-exported updated entity",{id:W.id,entityType:W.entityType})}catch(W){w.error("Auto-export FAILED for updated entity",{entityType:Z,entityId:H,error:W instanceof Error?W.message:String(W),stack:W instanceof Error?W.stack:void 0})}return{success:!0}}),B("entity:deleted",async(Y)=>{let{entityId:Z,entityType:H}=Y.payload,W=Q.fileOps.getFilePath(Z,H);if(await H6w(W).then(()=>!0,()=>!1))await f6w(W),w.debug("Auto-deleted entity file",{id:Z,entityType:H,path:W});return{success:!0}}),w.debug("Setup auto-sync for entity events",{entityTypes:$})}function vm1(A,Q,w){Q.setJobQueueCallback(async($)=>{let B=[{type:$.type,data:W6w.parse($.data)}];return A.jobs.enqueueBatch(B,{priority:5,source:"directory-sync-watcher",rootJobId:g4(),metadata:{operationType:"file_operations",operationTarget:w,pluginId:"directory-sync"}})})}fA();import{readdir as ym1,mkdir as U6w,copyFile as G6w}from"fs/promises";import{join as Cm1,resolve as Td0}from"path";import{join as K6w}from"path";async function hm1(A){if(!await J5(K6w(A,".git")))return!1;try{return await dU(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function D6w(A,Q){if(!await J5(A))return!0;if((await ym1(A)).filter((B)=>!B.startsWith(".")&&!B.startsWith("_")).length>0)return!1;if(await hm1(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function gm1(A,Q){let w=await ym1(A,{withFileTypes:!0});for(let $ of w){let B=Cm1(A,$.name),X=Cm1(Q,$.name);if($.isDirectory()){if(!await J5(X))await U6w(X,{recursive:!0});await gm1(B,X)}else await G6w(B,X)}}async function Em1(A,Q,w){let $=Td0(process.cwd(),A);w=w?Td0(w):Td0(process.cwd(),"seed-content");let B=await D6w($,Q);if(B&&await J5(w))Q.debug("Copying seed content to brain-data directory"),await gm1(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 Tm1(A,Q,w,$,B){let X=!1,Y=async()=>{if(X)return;X=!0;let Z=Q();if(w.seedContent){let H=w.syncPath??A.dataDir;await Em1(H,$,w.seedContentPath)}try{if(B){$.debug("Git enabled \u2014 pulling before import");let W=await B.pull();if(W.files.length>0)$.info("Pulled changes from remote",{filesChanged:W.files.length})}$.debug("Starting initial sync");let H=await Z.sync();$.debug("Initial sync completed",{imported:H.import.imported,failed:H.import.failed,duration:H.duration}),await A.messaging.send({type:x_.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(H){$.error("Initial sync failed",H),await A.messaging.send({type:x_.initialSyncCompleted,payload:{success:!1,error:dA(H)},...{broadcast:!0}})}};A.messaging.subscribe(x_.pluginsRegistered,async()=>{return $.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}class Sd0{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 md0{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 Sm1(A,Q,w,$){let B=new md0(()=>{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 H=A.subscribe(Z,async()=>{return B.trigger(),{success:!0}});Y.push(H)}return()=>{B.dispose();for(let Z of Y)Z()}}function mm1(A,Q,w,$,B){if($<=0)return()=>{};let X=$*60*1000,Y=!1,Z=async()=>{if(Y)return;Y=!0;try{let{files:W,result:K}=await A.withLock(async()=>{let U=await A.pull();if(U.files.length===0)return{files:[],result:null};let G=await Q.queueSyncBatch(w,"periodic-sync");return{files:U.files,result:G}});if(W.length>0)B.info("Periodic sync: pulled changes",{filesChanged:W.length});if(K)B.debug("Periodic sync: queued imports",{importOperations:K.importOperationsCount,totalFiles:K.totalFiles})}catch(W){B.error("Periodic git sync failed",{error:W})}finally{Y=!1}},H=setInterval(()=>{Z()},X);return B.info("Started periodic git sync",{intervalMinutes:$}),()=>{clearInterval(H)}}import{spawnSync as cm1}from"child_process";import{cpSync as q6w,existsSync as um1,mkdirSync as z6w,mkdtempSync as V6w,rmSync as J6w}from"fs";import{tmpdir as F6w}from"os";import{fileURLToPath as I6w}from"url";import{join as b6w,resolve as L6w}from"path";function db(A,Q){let w=cm1("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 k6w(A){return A.startsWith("file://")}function _6w(A){return I6w(A)}function N6w(A,Q){return cm1("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function lm1(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!k6w(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",w=_6w(A.gitUrl),$=L6w(A.seedContentPath);if(!um1($))throw Error(`Seed content path not found: ${$}`);if(!um1(w))A.logger.debug("Creating local bare content remote",{remotePath:w,branch:Q}),z6w(w,{recursive:!0}),db(process.cwd(),["init","--bare",`--initial-branch=${Q}`,w]);if(N6w(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=V6w(b6w(F6w(),"directory-sync-seed-"));try{db(B,["init",`--initial-branch=${Q}`]),db(B,["config","user.name",A.authorName??"Brain"]),db(B,["config","user.email",A.authorEmail??"brain@localhost"]),q6w($,B,{recursive:!0,filter:(X)=>!X.split("/").includes(".git")}),db(B,["add","."]),db(B,["commit","-m","seed content remote"]),db(B,["remote","add","origin",A.gitUrl]),db(B,["push","-u","origin",Q])}finally{J6w(B,{recursive:!0,force:!0})}}function pm1(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(H){return{success:!1,error:H instanceof Error?H.message:"Export failed"}}}),Y("entity:import:request",async(Z)=>{try{let H=Q(),W=Z.payload.paths,K=await H.importEntities(W);if(W&&W.length>0)await H.removeOrphanedEntities();return{success:!0,data:K}}catch(H){return{success:!1,error:H instanceof Error?H.message:"Import failed"}}}),Y("sync:status:request",async()=>{try{let H=await Q().getStatus();return{success:!0,data:{syncPath:H.syncPath,isInitialized:H.exists,watchEnabled:H.watching,lastSync:H.lastSync?.toISOString()??null,totalFiles:H.stats.totalFiles,byEntityType:H.stats.byEntityType,git:await j6w(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(H){return{success:!1,error:H instanceof Error?H.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 j6w(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}}fA();C0();fA();C0();function im1(A,Q){return i6(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",f.object({entityType:f.string().describe("Entity type (e.g. post, note, link)"),id:f.string().describe("Entity ID"),sha:f.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:f.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(w)=>{let $=`${w.entityType}/${w.id}.md`;try{if(w.sha){let X=await Q.show(w.sha,$);return p5({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 p5({commits:[]},`No history found for ${w.entityType}/${w.id}`);return p5({commits:B,entityType:w.entityType,id:w.id},`${B.length} version${B.length===1?"":"s"} found`)}catch(B){return s7(B instanceof Error?B.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function dm1(A,Q,w,$){let B=[i6(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.",f.object({}),async(X,Y)=>{try{let Z=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${w}`,H={interfaceType:Y.interfaceType,channelId:Y.channelId};if($){let K=await Q.jobs.enqueue({type:"sync-request",data:{source:Z,interfaceType:H.interfaceType,channelId:H.channelId},toolContext:Y});return p5({jobId:K,status:"queued",gitPulled:!0},"Sync queued: git pull and filesystem scan will run in the background")}let W=await A.queueSyncBatch(Q,Z,H);if(!W)return p5({gitPulled:!1},"No files to sync");return p5({batchId:W.batchId,importOperations:W.importOperationsCount,totalFiles:W.totalFiles,gitPulled:!1},`Sync started: ${W.importOperationsCount} import jobs queued for ${W.totalFiles} files`)}catch(Z){return s7(Z instanceof Error?Z.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),i6(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.",f.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 p5(Y)}catch(X){return s7(X instanceof Error?X.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if($)B.push(im1(w,$));return B}var nm1={name:"@brains/directory-sync",version:"0.2.0-alpha.168",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 ud0 extends Uw{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",nm1,A,hr)}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:Cr,basePrompt:"",formatter:new wX0,requiredPermission:"anchor"}});let $=this.config.syncPath??A.dataDir;this.directorySync=new br({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(Rm1(A,B,this.logger,this.config.entityTypes),this.config.autoSync)vm1(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 lm1({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 Rd0({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 YX0(this.logger.child("DirectorySyncRequestJobHandler"),A,this.requireDirectorySync(),this.gitSync)),this.gitCleanups.push(Sm1(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(mm1(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)Tm1(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync);pm1(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git,()=>this.gitSync)}async getTools(){let A=this.requireDirectorySync();return dm1(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 br({...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){xm1(A,this.requireDirectorySync(),this.logger)}}function JP(A={}){return new ud0(A)}fA();C0();var rm1={name:"@brains/email-resend",version:"0.2.0-alpha.168",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 O6w=f.object({apiKey:f.string().min(1).optional(),from:f.string().min(1).optional()}),x6w=f.looseObject({id:f.string().optional()});class om1 extends Uw{fetchImpl;constructor(A={},Q={}){super("email-resend",rm1,A,O6w);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(UB0,async(w)=>{let $=ocA.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=x6w.parse(await $.json());return B.id?{status:"sent",id:B.id}:{status:"sent"}}}function KX0(A={}){return new om1(A)}fA();import{render as y12}from"preact-render-to-string";import{h as AM}from"preact";function sm1(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=sm1(A[Q]))&&($&&($+=" "),$+=w)}else for(w in A)A[w]&&($&&($+=" "),$+=w);return $}function qg(){for(var A,Q,w=0,$="",B=arguments.length;w<B;w++)(A=arguments[w])&&(Q=sm1(A))&&($&&($+=" "),$+=Q);return $}var R6w=(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},v6w=(A,Q)=>({classGroupId:A,validator:Q}),Bu1=(A=new Map,Q=null,w)=>({nextPart:A,validators:Q,classGroupId:w});var am1=[];var h6w=(A)=>{let Q=y6w(A),{conflictingClassGroups:w,conflictingClassGroupModifiers:$}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return C6w(Y);let Z=Y.split("-"),H=Z[0]===""&&Z.length>1?1:0;return Xu1(Z,H,Q)},getConflictingClassGroupIds:(Y,Z)=>{if(Z){let H=$[Y],W=w[Y];if(H){if(W)return R6w(W,H);return H}return W||am1}return w[Y]||am1}}},Xu1=(A,Q,w)=>{if(A.length-Q===0)return w.classGroupId;let B=A[Q],X=w.nextPart.get(B);if(X){let W=Xu1(A,Q+1,X);if(W)return W}let Y=w.validators;if(Y===null)return;let Z=Q===0?A.join("-"):A.slice(Q).join("-"),H=Y.length;for(let W=0;W<H;W++){let K=Y[W];if(K.validator(Z))return K.classGroupId}return},C6w=(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})(),y6w=(A)=>{let{theme:Q,classGroups:w}=A;return g6w(w,Q)},g6w=(A,Q)=>{let w=Bu1();for(let $ in A){let B=A[$];pd0(B,w,$,Q)}return w},pd0=(A,Q,w,$)=>{let B=A.length;for(let X=0;X<B;X++){let Y=A[X];E6w(Y,Q,w,$)}},E6w=(A,Q,w,$)=>{if(typeof A==="string"){T6w(A,Q,w);return}if(typeof A==="function"){S6w(A,Q,w,$);return}m6w(A,Q,w,$)},T6w=(A,Q,w)=>{let $=A===""?Q:Yu1(Q,A);$.classGroupId=w},S6w=(A,Q,w,$)=>{if(u6w(A)){pd0(A($),Q,w,$);return}if(Q.validators===null)Q.validators=[];Q.validators.push(v6w(w,A))},m6w=(A,Q,w,$)=>{let B=Object.entries(A),X=B.length;for(let Y=0;Y<X;Y++){let[Z,H]=B[Y];pd0(H,Yu1(Q,Z),w,$)}},Yu1=(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=Bu1(),w.nextPart.set(Y,Z);w=Z}return w},u6w=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,c6w=(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 l6w=[],tm1=(A,Q,w,$,B)=>({modifiers:A,hasImportantModifier:Q,baseClassName:w,maybePostfixModifierPosition:$,isExternal:B}),p6w=(A)=>{let{prefix:Q,experimentalParseClassName:w}=A,$=(B)=>{let X=[],Y=0,Z=0,H=0,W,K=B.length;for(let J=0;J<K;J++){let F=B[J];if(Y===0&&Z===0){if(F===":"){X.push(B.slice(H,J)),H=J+1;continue}if(F==="/"){W=J;continue}}if(F==="[")Y++;else if(F==="]")Y--;else if(F==="(")Z++;else if(F===")")Z--}let U=X.length===0?B:B.slice(H),G=U,q=!1;if(U.endsWith("!"))G=U.slice(0,-1),q=!0;else if(U.startsWith("!"))G=U.slice(1),q=!0;let V=W&&W>H?W-H:void 0;return tm1(X,q,G,V)};if(Q){let B=Q+":",X=$;$=(Y)=>Y.startsWith(B)?X(Y.slice(B.length)):tm1(l6w,!1,Y,void 0,!0)}if(w){let B=$;$=(X)=>w({className:X,parseClassName:B})}return $},i6w=(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]==="[",H=Q.has(Y);if(Z||H){if(B.length>0)B.sort(),$.push(...B),B=[];$.push(Y)}else B.push(Y)}if(B.length>0)B.sort(),$.push(...B);return $}},d6w=(A)=>({cache:c6w(A.cacheSize),parseClassName:p6w(A),sortModifiers:i6w(A),postfixLookupClassGroupIds:n6w(A),...h6w(A)}),n6w=(A)=>{let Q=Object.create(null),w=A.postfixLookupClassGroups;if(w)for(let $=0;$<w.length;$++)Q[w[$]]=!0;return Q},r6w=/\s+/,o6w=(A,Q)=>{let{parseClassName:w,getClassGroupId:$,getConflictingClassGroupIds:B,sortModifiers:X,postfixLookupClassGroupIds:Y}=Q,Z=[],H=A.trim().split(r6w),W="";for(let K=H.length-1;K>=0;K-=1){let U=H[K],{isExternal:G,modifiers:q,hasImportantModifier:V,baseClassName:J,maybePostfixModifierPosition:F}=w(U);if(G){W=U+(W.length>0?" "+W:W);continue}let k=!!F,j;if(k){let M=J.substring(0,F);j=$(M);let S=j&&Y[j]?$(J):void 0;if(S&&S!==j)j=S,k=!1}else j=$(J);if(!j){if(!k){W=U+(W.length>0?" "+W:W);continue}if(j=$(J),!j){W=U+(W.length>0?" "+W:W);continue}k=!1}let _=q.length===0?"":q.length===1?q[0]:X(q).join(":"),O=V?_+"!":_,R=O+j;if(Z.indexOf(R)>-1)continue;Z.push(R);let x=B(j,k);for(let M=0;M<x.length;++M){let S=x[M];Z.push(O+S)}W=U+(W.length>0?" "+W:W)}return W},s6w=(...A)=>{let Q=0,w,$,B="";while(Q<A.length)if(w=A[Q++]){if($=Zu1(w))B&&(B+=" "),B+=$}return B},Zu1=(A)=>{if(typeof A==="string")return A;let Q,w="";for(let $=0;$<A.length;$++)if(A[$]){if(Q=Zu1(A[$]))w&&(w+=" "),w+=Q}return w},em1=(A,...Q)=>{let w,$,B,X,Y=(H)=>{let W=Q.reduce((K,U)=>U(K),A());return w=d6w(W),$=w.cache.get,B=w.cache.set,X=Z,Z(H)},Z=(H)=>{let W=$(H);if(W)return W;let K=o6w(H,w);return B(H,K),K};return X=Y,(...H)=>X(s6w(...H))},a6w=[],l9=(A)=>{let Q=(w)=>w[A]||a6w;return Q.isThemeGetter=!0,Q},fu1=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,Hu1=/^\((?:(\w[\w-]*):)?(.+)\)$/i,t6w=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,e6w=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,A$w=/\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$/,Q$w=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,w$w=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,$$w=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,nb=(A)=>t6w.test(A),aw=(A)=>!!A&&!Number.isNaN(Number(A)),Uq=(A)=>!!A&&Number.isInteger(Number(A)),cd0=(A)=>A.endsWith("%")&&aw(A.slice(0,-1)),MV=(A)=>e6w.test(A),Wu1=()=>!0,B$w=(A)=>A$w.test(A)&&!Q$w.test(A),id0=()=>!1,X$w=(A)=>w$w.test(A),Y$w=(A)=>$$w.test(A),Z$w=(A)=>!R2(A)&&!y2(A),f$w=(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)),H$w=(A)=>rb(A,Gu1,id0),R2=(A)=>fu1.test(A),FP=(A)=>rb(A,Du1,B$w),Au1=(A)=>rb(A,V$w,aw),W$w=(A)=>rb(A,zu1,Wu1),K$w=(A)=>rb(A,qu1,id0),Qu1=(A)=>rb(A,Ku1,id0),U$w=(A)=>rb(A,Uu1,Y$w),UX0=(A)=>rb(A,Vu1,X$w),y2=(A)=>Hu1.test(A),yr=(A)=>IP(A,Du1),G$w=(A)=>IP(A,qu1),wu1=(A)=>IP(A,Ku1),D$w=(A)=>IP(A,Gu1),q$w=(A)=>IP(A,Uu1),GX0=(A)=>IP(A,Vu1,!0),z$w=(A)=>IP(A,zu1,!0),rb=(A,Q,w)=>{let $=fu1.exec(A);if($){if($[1])return Q($[1]);return w($[2])}return!1},IP=(A,Q,w=!1)=>{let $=Hu1.exec(A);if($){if($[1])return Q($[1]);return w}return!1},Ku1=(A)=>A==="position"||A==="percentage",Uu1=(A)=>A==="image"||A==="url",Gu1=(A)=>A==="length"||A==="size"||A==="bg-size",Du1=(A)=>A==="length",V$w=(A)=>A==="number",qu1=(A)=>A==="family-name",zu1=(A)=>A==="number"||A==="weight",Vu1=(A)=>A==="shadow";var $u1=()=>{let A=l9("color"),Q=l9("font"),w=l9("text"),$=l9("font-weight"),B=l9("tracking"),X=l9("leading"),Y=l9("breakpoint"),Z=l9("container"),H=l9("spacing"),W=l9("radius"),K=l9("shadow"),U=l9("inset-shadow"),G=l9("text-shadow"),q=l9("drop-shadow"),V=l9("blur"),J=l9("perspective"),F=l9("aspect"),k=l9("ease"),j=l9("animate"),_=()=>["auto","avoid","all","avoid-page","page","left","right","column"],O=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],R=()=>[...O(),y2,R2],x=()=>["auto","hidden","clip","visible","scroll"],M=()=>["auto","contain","none"],S=()=>[y2,R2,H],u=()=>[nb,"full","auto",...S()],n=()=>[Uq,"none","subgrid",y2,R2],e=()=>["auto",{span:["full",Uq,y2,R2]},Uq,y2,R2],X0=()=>[Uq,"auto",y2,R2],l=()=>["auto","min","max","fr",y2,R2],P=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],g=()=>["start","end","center","stretch","center-safe","end-safe"],y=()=>["auto",...S()],s=()=>[nb,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...S()],a=()=>[nb,"screen","full","dvw","lvw","svw","min","max","fit",...S()],D0=()=>[nb,"screen","full","lh","dvh","lvh","svh","min","max","fit",...S()],T=()=>[A,y2,R2],f0=()=>[...O(),wu1,Qu1,{position:[y2,R2]}],b0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],i=()=>["auto","cover","contain",D$w,H$w,{size:[y2,R2]}],u0=()=>[cd0,yr,FP],i0=()=>["","none","full",W,y2,R2],k0=()=>["",aw,yr,FP],_0=()=>["solid","dashed","dotted","double"],v0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],S0=()=>[aw,cd0,wu1,Qu1],j0=()=>["","none",V,y2,R2],P0=()=>["none",aw,y2,R2],E0=()=>["none",aw,y2,R2],T0=()=>[aw,y2,R2],n0=()=>[nb,"full",...S()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[MV],breakpoint:[MV],color:[Wu1],container:[MV],"drop-shadow":[MV],ease:["in","out","in-out"],font:[Z$w],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[MV],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[MV],shadow:[MV],spacing:["px",aw],text:[MV],"text-shadow":[MV],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",nb,R2,y2,F]}],container:["container"],"container-type":[{"@container":["","normal","size",y2,R2]}],"container-named":[f$w],columns:[{columns:[aw,R2,y2,Z]}],"break-after":[{"break-after":_()}],"break-before":[{"break-before":_()}],"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:x()}],"overflow-x":[{"overflow-x":x()}],"overflow-y":[{"overflow-y":x()}],overscroll:[{overscroll:M()}],"overscroll-x":[{"overscroll-x":M()}],"overscroll-y":[{"overscroll-y":M()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:u()}],"inset-x":[{"inset-x":u()}],"inset-y":[{"inset-y":u()}],start:[{"inset-s":u(),start:u()}],end:[{"inset-e":u(),end:u()}],"inset-bs":[{"inset-bs":u()}],"inset-be":[{"inset-be":u()}],top:[{top:u()}],right:[{right:u()}],bottom:[{bottom:u()}],left:[{left:u()}],visibility:["visible","invisible","collapse"],z:[{z:[Uq,"auto",y2,R2]}],basis:[{basis:[nb,"full","auto",Z,...S()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[aw,nb,"auto","initial","none",R2]}],grow:[{grow:["",aw,y2,R2]}],shrink:[{shrink:["",aw,y2,R2]}],order:[{order:[Uq,"first","last","none",y2,R2]}],"grid-cols":[{"grid-cols":n()}],"col-start-end":[{col:e()}],"col-start":[{"col-start":X0()}],"col-end":[{"col-end":X0()}],"grid-rows":[{"grid-rows":n()}],"row-start-end":[{row:e()}],"row-start":[{"row-start":X0()}],"row-end":[{"row-end":X0()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":l()}],"auto-rows":[{"auto-rows":l()}],gap:[{gap:S()}],"gap-x":[{"gap-x":S()}],"gap-y":[{"gap-y":S()}],"justify-content":[{justify:[...P(),"normal"]}],"justify-items":[{"justify-items":[...g(),"normal"]}],"justify-self":[{"justify-self":["auto",...g()]}],"align-content":[{content:["normal",...P()]}],"align-items":[{items:[...g(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...g(),{baseline:["","last"]}]}],"place-content":[{"place-content":P()}],"place-items":[{"place-items":[...g(),"baseline"]}],"place-self":[{"place-self":["auto",...g()]}],p:[{p:S()}],px:[{px:S()}],py:[{py:S()}],ps:[{ps:S()}],pe:[{pe:S()}],pbs:[{pbs:S()}],pbe:[{pbe:S()}],pt:[{pt:S()}],pr:[{pr:S()}],pb:[{pb:S()}],pl:[{pl:S()}],m:[{m:y()}],mx:[{mx:y()}],my:[{my:y()}],ms:[{ms:y()}],me:[{me:y()}],mbs:[{mbs:y()}],mbe:[{mbe:y()}],mt:[{mt:y()}],mr:[{mr:y()}],mb:[{mb:y()}],ml:[{ml:y()}],"space-x":[{"space-x":S()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":S()}],"space-y-reverse":["space-y-reverse"],size:[{size:s()}],"inline-size":[{inline:["auto",...a()]}],"min-inline-size":[{"min-inline":["auto",...a()]}],"max-inline-size":[{"max-inline":["none",...a()]}],"block-size":[{block:["auto",...D0()]}],"min-block-size":[{"min-block":["auto",...D0()]}],"max-block-size":[{"max-block":["none",...D0()]}],w:[{w:[Z,"screen",...s()]}],"min-w":[{"min-w":[Z,"screen","none",...s()]}],"max-w":[{"max-w":[Z,"screen","none","prose",{screen:[Y]},...s()]}],h:[{h:["screen","lh",...s()]}],"min-h":[{"min-h":["screen","lh","none",...s()]}],"max-h":[{"max-h":["screen","lh",...s()]}],"font-size":[{text:["base",w,yr,FP]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[$,z$w,W$w]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",cd0,R2]}],"font-family":[{font:[G$w,K$w,Q]}],"font-features":[{"font-features":[R2]}],"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,y2,R2]}],"line-clamp":[{"line-clamp":[aw,"none",y2,Au1]}],leading:[{leading:[X,...S()]}],"list-image":[{"list-image":["none",y2,R2]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",y2,R2]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:T()}],"text-color":[{text:T()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[..._0(),"wavy"]}],"text-decoration-thickness":[{decoration:[aw,"from-font","auto",y2,FP]}],"text-decoration-color":[{decoration:T()}],"underline-offset":[{"underline-offset":[aw,"auto",y2,R2]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:S()}],"tab-size":[{tab:[Uq,y2,R2]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",y2,R2]}],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",y2,R2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:f0()}],"bg-repeat":[{bg:b0()}],"bg-size":[{bg:i()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},Uq,y2,R2],radial:["",y2,R2],conic:[Uq,y2,R2]},q$w,U$w]}],"bg-color":[{bg:T()}],"gradient-from-pos":[{from:u0()}],"gradient-via-pos":[{via:u0()}],"gradient-to-pos":[{to:u0()}],"gradient-from":[{from:T()}],"gradient-via":[{via:T()}],"gradient-to":[{to:T()}],rounded:[{rounded:i0()}],"rounded-s":[{"rounded-s":i0()}],"rounded-e":[{"rounded-e":i0()}],"rounded-t":[{"rounded-t":i0()}],"rounded-r":[{"rounded-r":i0()}],"rounded-b":[{"rounded-b":i0()}],"rounded-l":[{"rounded-l":i0()}],"rounded-ss":[{"rounded-ss":i0()}],"rounded-se":[{"rounded-se":i0()}],"rounded-ee":[{"rounded-ee":i0()}],"rounded-es":[{"rounded-es":i0()}],"rounded-tl":[{"rounded-tl":i0()}],"rounded-tr":[{"rounded-tr":i0()}],"rounded-br":[{"rounded-br":i0()}],"rounded-bl":[{"rounded-bl":i0()}],"border-w":[{border:k0()}],"border-w-x":[{"border-x":k0()}],"border-w-y":[{"border-y":k0()}],"border-w-s":[{"border-s":k0()}],"border-w-e":[{"border-e":k0()}],"border-w-bs":[{"border-bs":k0()}],"border-w-be":[{"border-be":k0()}],"border-w-t":[{"border-t":k0()}],"border-w-r":[{"border-r":k0()}],"border-w-b":[{"border-b":k0()}],"border-w-l":[{"border-l":k0()}],"divide-x":[{"divide-x":k0()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":k0()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[..._0(),"hidden","none"]}],"divide-style":[{divide:[..._0(),"hidden","none"]}],"border-color":[{border:T()}],"border-color-x":[{"border-x":T()}],"border-color-y":[{"border-y":T()}],"border-color-s":[{"border-s":T()}],"border-color-e":[{"border-e":T()}],"border-color-bs":[{"border-bs":T()}],"border-color-be":[{"border-be":T()}],"border-color-t":[{"border-t":T()}],"border-color-r":[{"border-r":T()}],"border-color-b":[{"border-b":T()}],"border-color-l":[{"border-l":T()}],"divide-color":[{divide:T()}],"outline-style":[{outline:[..._0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[aw,y2,R2]}],"outline-w":[{outline:["",aw,yr,FP]}],"outline-color":[{outline:T()}],shadow:[{shadow:["","none",K,GX0,UX0]}],"shadow-color":[{shadow:T()}],"inset-shadow":[{"inset-shadow":["none",U,GX0,UX0]}],"inset-shadow-color":[{"inset-shadow":T()}],"ring-w":[{ring:k0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:T()}],"ring-offset-w":[{"ring-offset":[aw,FP]}],"ring-offset-color":[{"ring-offset":T()}],"inset-ring-w":[{"inset-ring":k0()}],"inset-ring-color":[{"inset-ring":T()}],"text-shadow":[{"text-shadow":["none",G,GX0,UX0]}],"text-shadow-color":[{"text-shadow":T()}],opacity:[{opacity:[aw,y2,R2]}],"mix-blend":[{"mix-blend":[...v0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":v0()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[aw]}],"mask-image-linear-from-pos":[{"mask-linear-from":S0()}],"mask-image-linear-to-pos":[{"mask-linear-to":S0()}],"mask-image-linear-from-color":[{"mask-linear-from":T()}],"mask-image-linear-to-color":[{"mask-linear-to":T()}],"mask-image-t-from-pos":[{"mask-t-from":S0()}],"mask-image-t-to-pos":[{"mask-t-to":S0()}],"mask-image-t-from-color":[{"mask-t-from":T()}],"mask-image-t-to-color":[{"mask-t-to":T()}],"mask-image-r-from-pos":[{"mask-r-from":S0()}],"mask-image-r-to-pos":[{"mask-r-to":S0()}],"mask-image-r-from-color":[{"mask-r-from":T()}],"mask-image-r-to-color":[{"mask-r-to":T()}],"mask-image-b-from-pos":[{"mask-b-from":S0()}],"mask-image-b-to-pos":[{"mask-b-to":S0()}],"mask-image-b-from-color":[{"mask-b-from":T()}],"mask-image-b-to-color":[{"mask-b-to":T()}],"mask-image-l-from-pos":[{"mask-l-from":S0()}],"mask-image-l-to-pos":[{"mask-l-to":S0()}],"mask-image-l-from-color":[{"mask-l-from":T()}],"mask-image-l-to-color":[{"mask-l-to":T()}],"mask-image-x-from-pos":[{"mask-x-from":S0()}],"mask-image-x-to-pos":[{"mask-x-to":S0()}],"mask-image-x-from-color":[{"mask-x-from":T()}],"mask-image-x-to-color":[{"mask-x-to":T()}],"mask-image-y-from-pos":[{"mask-y-from":S0()}],"mask-image-y-to-pos":[{"mask-y-to":S0()}],"mask-image-y-from-color":[{"mask-y-from":T()}],"mask-image-y-to-color":[{"mask-y-to":T()}],"mask-image-radial":[{"mask-radial":[y2,R2]}],"mask-image-radial-from-pos":[{"mask-radial-from":S0()}],"mask-image-radial-to-pos":[{"mask-radial-to":S0()}],"mask-image-radial-from-color":[{"mask-radial-from":T()}],"mask-image-radial-to-color":[{"mask-radial-to":T()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":O()}],"mask-image-conic-pos":[{"mask-conic":[aw]}],"mask-image-conic-from-pos":[{"mask-conic-from":S0()}],"mask-image-conic-to-pos":[{"mask-conic-to":S0()}],"mask-image-conic-from-color":[{"mask-conic-from":T()}],"mask-image-conic-to-color":[{"mask-conic-to":T()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:f0()}],"mask-repeat":[{mask:b0()}],"mask-size":[{mask:i()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",y2,R2]}],filter:[{filter:["","none",y2,R2]}],blur:[{blur:j0()}],brightness:[{brightness:[aw,y2,R2]}],contrast:[{contrast:[aw,y2,R2]}],"drop-shadow":[{"drop-shadow":["","none",q,GX0,UX0]}],"drop-shadow-color":[{"drop-shadow":T()}],grayscale:[{grayscale:["",aw,y2,R2]}],"hue-rotate":[{"hue-rotate":[aw,y2,R2]}],invert:[{invert:["",aw,y2,R2]}],saturate:[{saturate:[aw,y2,R2]}],sepia:[{sepia:["",aw,y2,R2]}],"backdrop-filter":[{"backdrop-filter":["","none",y2,R2]}],"backdrop-blur":[{"backdrop-blur":j0()}],"backdrop-brightness":[{"backdrop-brightness":[aw,y2,R2]}],"backdrop-contrast":[{"backdrop-contrast":[aw,y2,R2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",aw,y2,R2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[aw,y2,R2]}],"backdrop-invert":[{"backdrop-invert":["",aw,y2,R2]}],"backdrop-opacity":[{"backdrop-opacity":[aw,y2,R2]}],"backdrop-saturate":[{"backdrop-saturate":[aw,y2,R2]}],"backdrop-sepia":[{"backdrop-sepia":["",aw,y2,R2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":S()}],"border-spacing-x":[{"border-spacing-x":S()}],"border-spacing-y":[{"border-spacing-y":S()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",y2,R2]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[aw,"initial",y2,R2]}],ease:[{ease:["linear","initial",k,y2,R2]}],delay:[{delay:[aw,y2,R2]}],animate:[{animate:["none",j,y2,R2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[J,y2,R2]}],"perspective-origin":[{"perspective-origin":R()}],rotate:[{rotate:P0()}],"rotate-x":[{"rotate-x":P0()}],"rotate-y":[{"rotate-y":P0()}],"rotate-z":[{"rotate-z":P0()}],scale:[{scale:E0()}],"scale-x":[{"scale-x":E0()}],"scale-y":[{"scale-y":E0()}],"scale-z":[{"scale-z":E0()}],"scale-3d":["scale-3d"],skew:[{skew:T0()}],"skew-x":[{"skew-x":T0()}],"skew-y":[{"skew-y":T0()}],transform:[{transform:[y2,R2,"","none","gpu","cpu"]}],"transform-origin":[{origin:R()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:n0()}],"translate-x":[{"translate-x":n0()}],"translate-y":[{"translate-y":n0()}],"translate-z":[{"translate-z":n0()}],"translate-none":["translate-none"],zoom:[{zoom:[Uq,y2,R2]}],accent:[{accent:T()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:T()}],"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",y2,R2]}],"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":T()}],"scrollbar-track-color":[{"scrollbar-track":T()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":S()}],"scroll-mx":[{"scroll-mx":S()}],"scroll-my":[{"scroll-my":S()}],"scroll-ms":[{"scroll-ms":S()}],"scroll-me":[{"scroll-me":S()}],"scroll-mbs":[{"scroll-mbs":S()}],"scroll-mbe":[{"scroll-mbe":S()}],"scroll-mt":[{"scroll-mt":S()}],"scroll-mr":[{"scroll-mr":S()}],"scroll-mb":[{"scroll-mb":S()}],"scroll-ml":[{"scroll-ml":S()}],"scroll-p":[{"scroll-p":S()}],"scroll-px":[{"scroll-px":S()}],"scroll-py":[{"scroll-py":S()}],"scroll-ps":[{"scroll-ps":S()}],"scroll-pe":[{"scroll-pe":S()}],"scroll-pbs":[{"scroll-pbs":S()}],"scroll-pbe":[{"scroll-pbe":S()}],"scroll-pt":[{"scroll-pt":S()}],"scroll-pr":[{"scroll-pr":S()}],"scroll-pb":[{"scroll-pb":S()}],"scroll-pl":[{"scroll-pl":S()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",y2,R2]}],fill:[{fill:["none",...T()]}],"stroke-w":[{stroke:[aw,yr,FP,Au1]}],stroke:[{stroke:["none",...T()]}],"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"]}},J$w=(A,{cacheSize:Q,prefix:w,experimentalParseClassName:$,extend:B={},override:X={}})=>{return zg(A,"cacheSize",Q),zg(A,"prefix",w),zg(A,"experimentalParseClassName",$),DX0(A.theme,X.theme),DX0(A.classGroups,X.classGroups),DX0(A.conflictingClassGroups,X.conflictingClassGroups),DX0(A.conflictingClassGroupModifiers,X.conflictingClassGroupModifiers),zg(A,"postfixLookupClassGroups",X.postfixLookupClassGroups),zg(A,"orderSensitiveModifiers",X.orderSensitiveModifiers),qX0(A.theme,B.theme),qX0(A.classGroups,B.classGroups),qX0(A.conflictingClassGroups,B.conflictingClassGroups),qX0(A.conflictingClassGroupModifiers,B.conflictingClassGroupModifiers),ld0(A,B,"postfixLookupClassGroups"),ld0(A,B,"orderSensitiveModifiers"),A},zg=(A,Q,w)=>{if(w!==void 0)A[Q]=w},DX0=(A,Q)=>{if(Q)for(let w in Q)zg(A,w,Q[w])},qX0=(A,Q)=>{if(Q)for(let w in Q)ld0(A,Q,w)},ld0=(A,Q,w)=>{let $=Q[w];if($!==void 0)A[w]=A[w]?A[w].concat($):$},zX0=(A,...Q)=>typeof A==="function"?em1($u1,A,...Q):em1(()=>J$w($u1(),A),...Q);var F$w=zX0({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 g2(...A){return F$w(qg(A))}var Ju1=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,Fu1=qg,m$=(A,Q)=>(w)=>{var $;if((Q===null||Q===void 0?void 0:Q.variants)==null)return Fu1(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((W)=>{let K=w===null||w===void 0?void 0:w[W],U=X===null||X===void 0?void 0:X[W];if(K===null)return null;let G=Ju1(K)||Ju1(U);return B[W][G]}),Z=w&&Object.entries(w).reduce((W,K)=>{let[U,G]=K;if(G===void 0)return W;return W[U]=G,W},{}),H=Q===null||Q===void 0?void 0:($=Q.compoundVariants)===null||$===void 0?void 0:$.reduce((W,K)=>{let{class:U,className:G,...q}=K;return Object.entries(q).every((V)=>{let[J,F]=V;return Array.isArray(F)?F.includes({...X,...Z}[J]):{...X,...Z}[J]===F})?[...W,U,G]:W},[]);return Fu1(A,Y,H,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className)};import{jsxDEV as dd0}from"preact/jsx-dev-runtime";var Iu1=m$("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 nd0({variant:A,title:Q,children:w,className:$}){return dd0("div",{className:g2(Iu1({variant:A}),$),role:"alert",children:[Q&&dd0("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),dd0("div",{className:g2(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 I$w}from"preact/jsx-dev-runtime";var bu1=m$("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 bP({variant:A,size:Q,className:w,children:$,ssrOnClick:B,type:X="button",...Y}){return I$w("button",{type:X,className:g2(bu1({variant:A,size:Q}),w),...Y,...B&&{onclick:B},children:$},void 0,!1,void 0,this)}import{jsxDEV as b$w}from"preact/jsx-dev-runtime";var Lu1=m$("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 p9({href:A,children:Q,variant:w,size:$,external:B=!1,className:X,"aria-label":Y}){let Z=B?{target:"_blank",rel:"noopener noreferrer"}:{};return b$w("a",{href:A,className:g2(Lu1({variant:w,size:$}),X),"aria-label":Y,...Z,children:Q},void 0,!1,void 0,this)}import{jsxDEV as VX0}from"preact/jsx-dev-runtime";var ku1=m$("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"}}),L$w={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function Vg({variant:A,size:Q,className:w}){let $=L$w[Q??"md"];return VX0("button",{onclick:"toggleTheme()",type:"button",className:g2(ku1({variant:A,size:Q}),w),"aria-label":"Toggle dark mode",children:VX0("svg",{className:g2($,"transition-colors"),fill:"none",stroke:"currentColor",strokeWidth:1.6,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[VX0("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),VX0("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 rd0}from"preact/jsx-dev-runtime";var _u1=m$("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function JX0({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 rd0("ul",{className:g2(_u1({orientation:$}),Q),children:[X.map((Y)=>rd0("li",{children:rd0("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 xw8}from"preact/jsx-dev-runtime";import{jsxDEV as hw8}from"preact/jsx-dev-runtime";import{createContext as k$w,h as _$w}from"preact";import{useContext as N$w}from"preact/hooks";var od0=k$w(null);function Jg({headCollector:A,children:Q}){return _$w(od0.Provider,{value:A},Q)}function Nu1(){return N$w(od0)}function Bw(A){let Q=Nu1();if(Q)Q.setHeadProps(A);return null}import{createContext as wXw,h as $Xw}from"preact";import{useContext as BXw}from"preact/hooks";ax0();var yi1=D1(Ci1(),1),AXw=new U$0({gfm:!0,breaks:!0}),QXw={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 Ir0(A,Q){let{imageRenderer:w}=Q??{},B=(w?new U$0({gfm:!0,breaks:!0}).use({renderer:{image({href:X,title:Y,text:Z}){return w(X,Y,Z)??!1}}}):AXw).parse(A);return B=B.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
|
|
5761
|
+
`)}}fA();class $X0 extends z6{directorySync;constructor(A,Q,w){super(A,{schema:yd0,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}}}fA();class BX0 extends z6{directorySync;constructor(A,Q,w){super(A,{schema:Cd0,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}}}fA();class XX0 extends z6{directorySync;context;constructor(A,Q,w){super(A,{schema:vd0,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 H=B==="export"?10:60;await w.report({progress:H,message:"Exporting entities to directory"}),Y=await this.exportWithProgress(A.entityTypes,w),await w.report({progress:100,message: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 H=(await Promise.all(A.map((K)=>w.getAsyncJobStatus(K)))).filter((K)=>K&&(K.status==="completed"||K.status==="failed")).length;if(H===A.length){this.logger.debug("All import jobs completed");return}if(Date.now()-X>$){this.logger.warn(`Timeout waiting for import jobs (${H}/${A.length} completed)`);return}let W=Math.round(H/A.length*100);return await Q.report({progress:50+Math.round(W*0.05),message:`Processing ${H}/${A.length} entities`}),await new Promise((K)=>setTimeout(K,B)),Y()};return Y()}summarizeDataForLog(A){return{operation:A.operation,syncDirection:A.syncDirection}}}fA();class YX0 extends z6{context;directorySync;gitSync;constructor(A,Q,w,$){super(A,{schema:hd0,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`}),A6w($)}summarizeDataForLog(A){return{source:A.source,interfaceType:A.interfaceType,channelId:A.channelId}}}function A6w(A){return{gitPulled:!0,batchQueued:!0,batchId:A.batchId,importOperations:A.importOperationsCount,totalFiles:A.totalFiles}}fA();class ZX0 extends z6{context;constructor(A,Q,w){super(A,{schema:QX0,jobTypeName:"directory-delete"});this.context=Q}async process(A,Q,w){let $=QX0.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}}}fA();C0();var Q6w=f.object({});class fX0 extends z6{directorySync;constructor(A,Q){super(A,{schema:Q6w,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`}),$}}fA();r4();K7();Q$();C0();r4();import{readFile as w6w,writeFile as $6w}from"fs/promises";var B6w=gd0,X6w=f.record(f.string(),f.unknown());class HX0 extends z6{context;fetcher;constructor(A,Q,w=kW){super(Q,{schema:B6w,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:Zw.INIT,message:`Reading file: ${$}`});let H;try{H=await w6w($,"utf-8")}catch(F){return this.logger.error("Failed to read file",{filePath:$,error:dA(F)}),j8.failure(F)}let W;try{W=p6(H)}catch(F){return this.logger.warn("Failed to parse markdown",{filePath:$,error:dA(F)}),j8.failure(F)}let K=X6w.safeParse(W.frontmatter),U=K.success?K.data:{};if(U.coverImageId)return this.logger.debug("File already has coverImageId, skipping",{filePath:$}),await this.reportProgress(w,{progress:Zw.COMPLETE,message:"Already converted"}),{success:!0,skipped:!0};await this.reportProgress(w,{progress:Zw.FETCH,message:"Checking for existing image"});let G=await this.context.entityService.listEntities({entityType:"image",options:{filter:{metadata:{sourceUrl:B}},limit:1}}),q;if(G[0])q=G[0].id,this.logger.debug("Reusing existing image entity",{sourceUrl:B,imageId:q}),await this.reportProgress(w,{progress:Zw.EXTRACT,message:`Reusing existing image: ${q}`});else{await this.reportProgress(w,{progress:Zw.PROCESS,message:`Fetching image from ${B}`});let F;try{F=await this.fetcher(B)}catch(x){return this.logger.error("Failed to fetch image",{sourceUrl:B,error:dA(x)}),j8.failure(x)}await this.reportProgress(w,{progress:Zw.GENERATE,message:"Creating image entity"});let{base64:k}=aF(F),j=$N(k),_=tF(k);if(!j||!_)return this.logger.error("Could not detect image format or dimensions",{sourceUrl:B}),j8.failure(Error("Could not detect image format or dimensions"));q=`${Y}-cover`;let O=`Cover image for ${X}`,R=Z??O;await this.context.entityService.createEntity({entity:{id:q,entityType:"image",content:F,metadata:{title:O,alt:R,format:j,width:_.width,height:_.height,sourceUrl:B}}}),this.logger.debug("Created image entity",{imageId:q,sourceUrl:B}),await this.reportProgress(w,{progress:Zw.EXTRACT,message:`Created image: ${q}`})}await this.reportProgress(w,{progress:Zw.SAVE,message:"Updating file"});let V={...U};delete V.coverImageUrl,delete V.coverImageAlt,V.coverImageId=q;let J=j_(V,W.content);try{await $6w($,J,"utf-8")}catch(F){return this.logger.error("Failed to write file",{filePath:$,error:dA(F)}),j8.failure(F)}return await this.reportProgress(w,{progress:Zw.COMPLETE,message:"Conversion complete"}),this.logger.info("Image conversion complete",{filePath:$,imageId:q,sourceUrl:B}),{success:!0,imageId:q}}catch(H){return this.logger.error("Image conversion job failed",{jobId:Q,filePath:$,error:dA(H)}),j8.failure(H)}}summarizeDataForLog(A){return{filePath:A.filePath,sourceUrl:A.sourceUrl,postSlug:A.postSlug}}}fA();r4();Q$();import{readFile as Y6w,writeFile as Z6w}from"fs/promises";class WX0 extends z6{converter;constructor(A,Q,w=kW){super(Q,{schema:Ed0,jobTypeName:"inline-image-convert"});this.converter=new Ir(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:Zw.INIT,message:`Reading file: ${$}`});let X;try{X=await Y6w($,"utf-8")}catch(H){let W=dA(H);return this.logger.error("Failed to read file",{filePath:$,error:W}),{success:!1,error:W}}await this.reportProgress(w,{progress:Zw.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:Zw.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:Zw.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:Zw.COMPLETE,message:"No images converted"}),{success:!0,skipped:!0,convertedCount:0};await this.reportProgress(w,{progress:Zw.SAVE,message:"Writing updated file"});try{await Z6w($,Z.content,"utf-8")}catch(H){let W=dA(H);return this.logger.error("Failed to write file",{filePath:$,error:W}),{success:!1,error:W}}return await this.reportProgress(w,{progress:Zw.COMPLETE,message:"Conversion complete"}),this.logger.info("Inline image conversion complete",{filePath:$,convertedCount:Z.convertedCount}),{success:!0,convertedCount:Z.convertedCount}}catch(X){let Y=dA(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 xm1(A,Q,w){let $=(B)=>w.child(B);A.jobs.registerHandler("directory-sync",new XX0($("DirectorySyncJobHandler"),A,Q)),A.jobs.registerHandler("directory-export",new $X0($("DirectoryExportJobHandler"),A,Q)),A.jobs.registerHandler("directory-import",new BX0($("DirectoryImportJobHandler"),A,Q)),A.jobs.registerHandler("directory-delete",new ZX0($("DirectoryDeleteJobHandler"),A,Q)),A.jobs.registerHandler("directory-cleanup",new fX0($("DirectoryCleanupJobHandler"),Q)),A.jobs.registerHandler("cover-image-convert",new HX0(A,$("CoverImageConversionJobHandler"))),A.jobs.registerHandler("inline-image-convert",new WX0(A,$("InlineImageConversionJobHandler"))),w.debug("Registered async job handlers")}fA();C0();import{unlink as f6w,access as H6w}from"fs/promises";var W6w=f.record(f.string(),f.unknown());function Rm1(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(H){w.error("Auto-export FAILED for created entity",{id:Z.id,entityType:Z.entityType,error:H instanceof Error?H.message:String(H),stack:H instanceof Error?H.stack:void 0})}return{success:!0}}),B("entity:updated",async(Y)=>{let{entityType:Z,entityId:H}=Y.payload;try{let W=await X.getEntity({entityType:Z,id:H});if(!W)return w.debug("Entity not found in DB, skipping export",{entityType:Z,entityId:H}),{success:!1};await Q.fileOps.writeEntity(W),w.debug("Auto-exported updated entity",{id:W.id,entityType:W.entityType})}catch(W){w.error("Auto-export FAILED for updated entity",{entityType:Z,entityId:H,error:W instanceof Error?W.message:String(W),stack:W instanceof Error?W.stack:void 0})}return{success:!0}}),B("entity:deleted",async(Y)=>{let{entityId:Z,entityType:H}=Y.payload,W=Q.fileOps.getFilePath(Z,H);if(await H6w(W).then(()=>!0,()=>!1))await f6w(W),w.debug("Auto-deleted entity file",{id:Z,entityType:H,path:W});return{success:!0}}),w.debug("Setup auto-sync for entity events",{entityTypes:$})}function vm1(A,Q,w){Q.setJobQueueCallback(async($)=>{let B=[{type:$.type,data:W6w.parse($.data)}];return A.jobs.enqueueBatch(B,{priority:5,source:"directory-sync-watcher",rootJobId:g4(),metadata:{operationType:"file_operations",operationTarget:w,pluginId:"directory-sync"}})})}fA();import{readdir as ym1,mkdir as U6w,copyFile as G6w}from"fs/promises";import{join as Cm1,resolve as Td0}from"path";import{join as K6w}from"path";async function hm1(A){if(!await J5(K6w(A,".git")))return!1;try{return await dU(A).revparse(["--verify","HEAD"]),!0}catch{return!1}}async function D6w(A,Q){if(!await J5(A))return!0;if((await ym1(A)).filter((B)=>!B.startsWith(".")&&!B.startsWith("_")).length>0)return!1;if(await hm1(A))return Q.debug("Git repository with history detected - skipping seed content",{path:A}),!1;return!0}async function gm1(A,Q){let w=await ym1(A,{withFileTypes:!0});for(let $ of w){let B=Cm1(A,$.name),X=Cm1(Q,$.name);if($.isDirectory()){if(!await J5(X))await U6w(X,{recursive:!0});await gm1(B,X)}else await G6w(B,X)}}async function Em1(A,Q,w){let $=Td0(process.cwd(),A);w=w?Td0(w):Td0(process.cwd(),"seed-content");let B=await D6w($,Q);if(B&&await J5(w))Q.debug("Copying seed content to brain-data directory"),await gm1(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 Tm1(A,Q,w,$,B){let X=!1,Y=async()=>{if(X)return;X=!0;let Z=Q();if(w.seedContent){let H=w.syncPath??A.dataDir;await Em1(H,$,w.seedContentPath)}try{if(B){$.debug("Git enabled \u2014 pulling before import");let W=await B.pull();if(W.files.length>0)$.info("Pulled changes from remote",{filesChanged:W.files.length})}$.debug("Starting initial sync");let H=await Z.sync();$.debug("Initial sync completed",{imported:H.import.imported,failed:H.import.failed,duration:H.duration}),await A.messaging.send({type:x_.initialSyncCompleted,payload:{success:!0},...{broadcast:!0}})}catch(H){$.error("Initial sync failed",H),await A.messaging.send({type:x_.initialSyncCompleted,payload:{success:!1,error:dA(H)},...{broadcast:!0}})}};A.messaging.subscribe(x_.pluginsRegistered,async()=>{return $.debug("Plugins registered, starting initial sync"),await Y(),{success:!0}})}class Sd0{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 md0{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 Sm1(A,Q,w,$){let B=new md0(()=>{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 H=A.subscribe(Z,async()=>{return B.trigger(),{success:!0}});Y.push(H)}return()=>{B.dispose();for(let Z of Y)Z()}}function mm1(A,Q,w,$,B){if($<=0)return()=>{};let X=$*60*1000,Y=!1,Z=async()=>{if(Y)return;Y=!0;try{let{files:W,result:K}=await A.withLock(async()=>{let U=await A.pull();if(U.files.length===0)return{files:[],result:null};let G=await Q.queueSyncBatch(w,"periodic-sync");return{files:U.files,result:G}});if(W.length>0)B.info("Periodic sync: pulled changes",{filesChanged:W.length});if(K)B.debug("Periodic sync: queued imports",{importOperations:K.importOperationsCount,totalFiles:K.totalFiles})}catch(W){B.error("Periodic git sync failed",{error:W})}finally{Y=!1}},H=setInterval(()=>{Z()},X);return B.info("Started periodic git sync",{intervalMinutes:$}),()=>{clearInterval(H)}}import{spawnSync as cm1}from"child_process";import{cpSync as q6w,existsSync as um1,mkdirSync as z6w,mkdtempSync as V6w,rmSync as J6w}from"fs";import{tmpdir as F6w}from"os";import{fileURLToPath as I6w}from"url";import{join as b6w,resolve as L6w}from"path";function db(A,Q){let w=cm1("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 k6w(A){return A.startsWith("file://")}function _6w(A){return I6w(A)}function N6w(A,Q){return cm1("git",["--git-dir",A,"show-ref","--verify","--quiet",`refs/heads/${Q}`]).status===0}async function lm1(A){if(!A.bootstrapFromSeed)return;if(!A.gitUrl||!k6w(A.gitUrl))return;if(!A.seedContentPath)throw Error("directory-sync git.bootstrapFromSeed requires seedContentPath for local file:// remotes");let Q=A.branch??"main",w=_6w(A.gitUrl),$=L6w(A.seedContentPath);if(!um1($))throw Error(`Seed content path not found: ${$}`);if(!um1(w))A.logger.debug("Creating local bare content remote",{remotePath:w,branch:Q}),z6w(w,{recursive:!0}),db(process.cwd(),["init","--bare",`--initial-branch=${Q}`,w]);if(N6w(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=V6w(b6w(F6w(),"directory-sync-seed-"));try{db(B,["init",`--initial-branch=${Q}`]),db(B,["config","user.name",A.authorName??"Brain"]),db(B,["config","user.email",A.authorEmail??"brain@localhost"]),q6w($,B,{recursive:!0,filter:(X)=>!X.split("/").includes(".git")}),db(B,["add","."]),db(B,["commit","-m","seed content remote"]),db(B,["remote","add","origin",A.gitUrl]),db(B,["push","-u","origin",Q])}finally{J6w(B,{recursive:!0,force:!0})}}function pm1(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(H){return{success:!1,error:H instanceof Error?H.message:"Export failed"}}}),Y("entity:import:request",async(Z)=>{try{let H=Q(),W=Z.payload.paths,K=await H.importEntities(W);if(W&&W.length>0)await H.removeOrphanedEntities();return{success:!0,data:K}}catch(H){return{success:!1,error:H instanceof Error?H.message:"Import failed"}}}),Y("sync:status:request",async()=>{try{let H=await Q().getStatus();return{success:!0,data:{syncPath:H.syncPath,isInitialized:H.exists,watchEnabled:H.watching,lastSync:H.lastSync?.toISOString()??null,totalFiles:H.stats.totalFiles,byEntityType:H.stats.byEntityType,git:await j6w(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(H){return{success:!1,error:H instanceof Error?H.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 j6w(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}}fA();C0();fA();C0();function im1(A,Q){return i6(A,"history","Get version history for an entity from git. Without sha: returns commit list. With sha: returns entity content at that version.",f.object({entityType:f.string().describe("Entity type (e.g. post, note, link)"),id:f.string().describe("Entity ID"),sha:f.string().optional().describe("Commit SHA to retrieve content at. Omit to list commit history."),limit:f.number().int().positive().optional().default(10).describe("Max commits to return (list mode only)")}),async(w)=>{let $=`${w.entityType}/${w.id}.md`;try{if(w.sha){let X=await Q.show(w.sha,$);return p5({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 p5({commits:[]},`No history found for ${w.entityType}/${w.id}`);return p5({commits:B,entityType:w.entityType,id:w.id},`${B.length} version${B.length===1?"":"s"} found`)}catch(B){return s7(B instanceof Error?B.message:"History lookup failed")}},{visibility:"anchor",sideEffects:"none"})}function dm1(A,Q,w,$){let B=[i6(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.",f.object({}),async(X,Y)=>{try{let Z=Y.channelId?`${Y.interfaceType}:${Y.channelId}`:`plugin:${w}`,H={interfaceType:Y.interfaceType,channelId:Y.channelId};if($){let K=await Q.jobs.enqueue({type:"sync-request",data:{source:Z,interfaceType:H.interfaceType,channelId:H.channelId},toolContext:Y});return p5({jobId:K,status:"queued",gitPulled:!0},"Sync queued: git pull and filesystem scan will run in the background")}let W=await A.queueSyncBatch(Q,Z,H);if(!W)return p5({gitPulled:!1},"No files to sync");return p5({batchId:W.batchId,importOperations:W.importOperationsCount,totalFiles:W.totalFiles,gitPulled:!1},`Sync started: ${W.importOperationsCount} import jobs queued for ${W.totalFiles} files`)}catch(Z){return s7(Z instanceof Error?Z.message:"Sync failed")}},{visibility:"anchor",sideEffects:"external",cli:{name:"sync"}}),i6(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.",f.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 p5(Y)}catch(X){return s7(X instanceof Error?X.message:"Status check failed")}},{visibility:"anchor",sideEffects:"none"})];if($)B.push(im1(w,$));return B}var nm1={name:"@brains/directory-sync",version:"0.2.0-alpha.169",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 ud0 extends Uw{directorySync;gitSync;gitCleanups=[];constructor(A={}){super("directory-sync",nm1,A,hr)}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:Cr,basePrompt:"",formatter:new wX0,requiredPermission:"anchor"}});let $=this.config.syncPath??A.dataDir;this.directorySync=new br({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(Rm1(A,B,this.logger,this.config.entityTypes),this.config.autoSync)vm1(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 lm1({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 Rd0({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 YX0(this.logger.child("DirectorySyncRequestJobHandler"),A,this.requireDirectorySync(),this.gitSync)),this.gitCleanups.push(Sm1(A.messaging,this.gitSync,this.config.commitDebounce,this.logger.child("GitAutoCommit"))),this.config.autoSync)this.gitCleanups.push(mm1(this.gitSync,this.requireDirectorySync(),A,this.config.syncInterval,this.logger.child("GitPeriodicSync")))}if(this.config.initialSync)Tm1(A,()=>this.requireDirectorySync(),this.config,this.logger,this.gitSync);pm1(A,()=>this.requireDirectorySync(),(Y)=>this.configure(Y),this.logger,this.config.git,()=>this.gitSync)}async getTools(){let A=this.requireDirectorySync();return dm1(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 br({...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){xm1(A,this.requireDirectorySync(),this.logger)}}function JP(A={}){return new ud0(A)}fA();C0();var rm1={name:"@brains/email-resend",version:"0.2.0-alpha.169",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 O6w=f.object({apiKey:f.string().min(1).optional(),from:f.string().min(1).optional()}),x6w=f.looseObject({id:f.string().optional()});class om1 extends Uw{fetchImpl;constructor(A={},Q={}){super("email-resend",rm1,A,O6w);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(UB0,async(w)=>{let $=ocA.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=x6w.parse(await $.json());return B.id?{status:"sent",id:B.id}:{status:"sent"}}}function KX0(A={}){return new om1(A)}fA();import{render as y12}from"preact-render-to-string";import{h as AM}from"preact";function sm1(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=sm1(A[Q]))&&($&&($+=" "),$+=w)}else for(w in A)A[w]&&($&&($+=" "),$+=w);return $}function qg(){for(var A,Q,w=0,$="",B=arguments.length;w<B;w++)(A=arguments[w])&&(Q=sm1(A))&&($&&($+=" "),$+=Q);return $}var R6w=(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},v6w=(A,Q)=>({classGroupId:A,validator:Q}),Bu1=(A=new Map,Q=null,w)=>({nextPart:A,validators:Q,classGroupId:w});var am1=[];var h6w=(A)=>{let Q=y6w(A),{conflictingClassGroups:w,conflictingClassGroupModifiers:$}=A;return{getClassGroupId:(Y)=>{if(Y.startsWith("[")&&Y.endsWith("]"))return C6w(Y);let Z=Y.split("-"),H=Z[0]===""&&Z.length>1?1:0;return Xu1(Z,H,Q)},getConflictingClassGroupIds:(Y,Z)=>{if(Z){let H=$[Y],W=w[Y];if(H){if(W)return R6w(W,H);return H}return W||am1}return w[Y]||am1}}},Xu1=(A,Q,w)=>{if(A.length-Q===0)return w.classGroupId;let B=A[Q],X=w.nextPart.get(B);if(X){let W=Xu1(A,Q+1,X);if(W)return W}let Y=w.validators;if(Y===null)return;let Z=Q===0?A.join("-"):A.slice(Q).join("-"),H=Y.length;for(let W=0;W<H;W++){let K=Y[W];if(K.validator(Z))return K.classGroupId}return},C6w=(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})(),y6w=(A)=>{let{theme:Q,classGroups:w}=A;return g6w(w,Q)},g6w=(A,Q)=>{let w=Bu1();for(let $ in A){let B=A[$];pd0(B,w,$,Q)}return w},pd0=(A,Q,w,$)=>{let B=A.length;for(let X=0;X<B;X++){let Y=A[X];E6w(Y,Q,w,$)}},E6w=(A,Q,w,$)=>{if(typeof A==="string"){T6w(A,Q,w);return}if(typeof A==="function"){S6w(A,Q,w,$);return}m6w(A,Q,w,$)},T6w=(A,Q,w)=>{let $=A===""?Q:Yu1(Q,A);$.classGroupId=w},S6w=(A,Q,w,$)=>{if(u6w(A)){pd0(A($),Q,w,$);return}if(Q.validators===null)Q.validators=[];Q.validators.push(v6w(w,A))},m6w=(A,Q,w,$)=>{let B=Object.entries(A),X=B.length;for(let Y=0;Y<X;Y++){let[Z,H]=B[Y];pd0(H,Yu1(Q,Z),w,$)}},Yu1=(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=Bu1(),w.nextPart.set(Y,Z);w=Z}return w},u6w=(A)=>("isThemeGetter"in A)&&A.isThemeGetter===!0,c6w=(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 l6w=[],tm1=(A,Q,w,$,B)=>({modifiers:A,hasImportantModifier:Q,baseClassName:w,maybePostfixModifierPosition:$,isExternal:B}),p6w=(A)=>{let{prefix:Q,experimentalParseClassName:w}=A,$=(B)=>{let X=[],Y=0,Z=0,H=0,W,K=B.length;for(let J=0;J<K;J++){let F=B[J];if(Y===0&&Z===0){if(F===":"){X.push(B.slice(H,J)),H=J+1;continue}if(F==="/"){W=J;continue}}if(F==="[")Y++;else if(F==="]")Y--;else if(F==="(")Z++;else if(F===")")Z--}let U=X.length===0?B:B.slice(H),G=U,q=!1;if(U.endsWith("!"))G=U.slice(0,-1),q=!0;else if(U.startsWith("!"))G=U.slice(1),q=!0;let V=W&&W>H?W-H:void 0;return tm1(X,q,G,V)};if(Q){let B=Q+":",X=$;$=(Y)=>Y.startsWith(B)?X(Y.slice(B.length)):tm1(l6w,!1,Y,void 0,!0)}if(w){let B=$;$=(X)=>w({className:X,parseClassName:B})}return $},i6w=(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]==="[",H=Q.has(Y);if(Z||H){if(B.length>0)B.sort(),$.push(...B),B=[];$.push(Y)}else B.push(Y)}if(B.length>0)B.sort(),$.push(...B);return $}},d6w=(A)=>({cache:c6w(A.cacheSize),parseClassName:p6w(A),sortModifiers:i6w(A),postfixLookupClassGroupIds:n6w(A),...h6w(A)}),n6w=(A)=>{let Q=Object.create(null),w=A.postfixLookupClassGroups;if(w)for(let $=0;$<w.length;$++)Q[w[$]]=!0;return Q},r6w=/\s+/,o6w=(A,Q)=>{let{parseClassName:w,getClassGroupId:$,getConflictingClassGroupIds:B,sortModifiers:X,postfixLookupClassGroupIds:Y}=Q,Z=[],H=A.trim().split(r6w),W="";for(let K=H.length-1;K>=0;K-=1){let U=H[K],{isExternal:G,modifiers:q,hasImportantModifier:V,baseClassName:J,maybePostfixModifierPosition:F}=w(U);if(G){W=U+(W.length>0?" "+W:W);continue}let k=!!F,j;if(k){let M=J.substring(0,F);j=$(M);let S=j&&Y[j]?$(J):void 0;if(S&&S!==j)j=S,k=!1}else j=$(J);if(!j){if(!k){W=U+(W.length>0?" "+W:W);continue}if(j=$(J),!j){W=U+(W.length>0?" "+W:W);continue}k=!1}let _=q.length===0?"":q.length===1?q[0]:X(q).join(":"),O=V?_+"!":_,R=O+j;if(Z.indexOf(R)>-1)continue;Z.push(R);let x=B(j,k);for(let M=0;M<x.length;++M){let S=x[M];Z.push(O+S)}W=U+(W.length>0?" "+W:W)}return W},s6w=(...A)=>{let Q=0,w,$,B="";while(Q<A.length)if(w=A[Q++]){if($=Zu1(w))B&&(B+=" "),B+=$}return B},Zu1=(A)=>{if(typeof A==="string")return A;let Q,w="";for(let $=0;$<A.length;$++)if(A[$]){if(Q=Zu1(A[$]))w&&(w+=" "),w+=Q}return w},em1=(A,...Q)=>{let w,$,B,X,Y=(H)=>{let W=Q.reduce((K,U)=>U(K),A());return w=d6w(W),$=w.cache.get,B=w.cache.set,X=Z,Z(H)},Z=(H)=>{let W=$(H);if(W)return W;let K=o6w(H,w);return B(H,K),K};return X=Y,(...H)=>X(s6w(...H))},a6w=[],l9=(A)=>{let Q=(w)=>w[A]||a6w;return Q.isThemeGetter=!0,Q},fu1=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,Hu1=/^\((?:(\w[\w-]*):)?(.+)\)$/i,t6w=/^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/,e6w=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,A$w=/\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$/,Q$w=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,w$w=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,$$w=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,nb=(A)=>t6w.test(A),aw=(A)=>!!A&&!Number.isNaN(Number(A)),Uq=(A)=>!!A&&Number.isInteger(Number(A)),cd0=(A)=>A.endsWith("%")&&aw(A.slice(0,-1)),MV=(A)=>e6w.test(A),Wu1=()=>!0,B$w=(A)=>A$w.test(A)&&!Q$w.test(A),id0=()=>!1,X$w=(A)=>w$w.test(A),Y$w=(A)=>$$w.test(A),Z$w=(A)=>!R2(A)&&!y2(A),f$w=(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)),H$w=(A)=>rb(A,Gu1,id0),R2=(A)=>fu1.test(A),FP=(A)=>rb(A,Du1,B$w),Au1=(A)=>rb(A,V$w,aw),W$w=(A)=>rb(A,zu1,Wu1),K$w=(A)=>rb(A,qu1,id0),Qu1=(A)=>rb(A,Ku1,id0),U$w=(A)=>rb(A,Uu1,Y$w),UX0=(A)=>rb(A,Vu1,X$w),y2=(A)=>Hu1.test(A),yr=(A)=>IP(A,Du1),G$w=(A)=>IP(A,qu1),wu1=(A)=>IP(A,Ku1),D$w=(A)=>IP(A,Gu1),q$w=(A)=>IP(A,Uu1),GX0=(A)=>IP(A,Vu1,!0),z$w=(A)=>IP(A,zu1,!0),rb=(A,Q,w)=>{let $=fu1.exec(A);if($){if($[1])return Q($[1]);return w($[2])}return!1},IP=(A,Q,w=!1)=>{let $=Hu1.exec(A);if($){if($[1])return Q($[1]);return w}return!1},Ku1=(A)=>A==="position"||A==="percentage",Uu1=(A)=>A==="image"||A==="url",Gu1=(A)=>A==="length"||A==="size"||A==="bg-size",Du1=(A)=>A==="length",V$w=(A)=>A==="number",qu1=(A)=>A==="family-name",zu1=(A)=>A==="number"||A==="weight",Vu1=(A)=>A==="shadow";var $u1=()=>{let A=l9("color"),Q=l9("font"),w=l9("text"),$=l9("font-weight"),B=l9("tracking"),X=l9("leading"),Y=l9("breakpoint"),Z=l9("container"),H=l9("spacing"),W=l9("radius"),K=l9("shadow"),U=l9("inset-shadow"),G=l9("text-shadow"),q=l9("drop-shadow"),V=l9("blur"),J=l9("perspective"),F=l9("aspect"),k=l9("ease"),j=l9("animate"),_=()=>["auto","avoid","all","avoid-page","page","left","right","column"],O=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],R=()=>[...O(),y2,R2],x=()=>["auto","hidden","clip","visible","scroll"],M=()=>["auto","contain","none"],S=()=>[y2,R2,H],u=()=>[nb,"full","auto",...S()],n=()=>[Uq,"none","subgrid",y2,R2],e=()=>["auto",{span:["full",Uq,y2,R2]},Uq,y2,R2],X0=()=>[Uq,"auto",y2,R2],l=()=>["auto","min","max","fr",y2,R2],P=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],g=()=>["start","end","center","stretch","center-safe","end-safe"],y=()=>["auto",...S()],s=()=>[nb,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...S()],a=()=>[nb,"screen","full","dvw","lvw","svw","min","max","fit",...S()],D0=()=>[nb,"screen","full","lh","dvh","lvh","svh","min","max","fit",...S()],T=()=>[A,y2,R2],f0=()=>[...O(),wu1,Qu1,{position:[y2,R2]}],b0=()=>["no-repeat",{repeat:["","x","y","space","round"]}],i=()=>["auto","cover","contain",D$w,H$w,{size:[y2,R2]}],u0=()=>[cd0,yr,FP],i0=()=>["","none","full",W,y2,R2],k0=()=>["",aw,yr,FP],_0=()=>["solid","dashed","dotted","double"],v0=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],S0=()=>[aw,cd0,wu1,Qu1],j0=()=>["","none",V,y2,R2],P0=()=>["none",aw,y2,R2],E0=()=>["none",aw,y2,R2],T0=()=>[aw,y2,R2],n0=()=>[nb,"full",...S()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[MV],breakpoint:[MV],color:[Wu1],container:[MV],"drop-shadow":[MV],ease:["in","out","in-out"],font:[Z$w],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[MV],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[MV],shadow:[MV],spacing:["px",aw],text:[MV],"text-shadow":[MV],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",nb,R2,y2,F]}],container:["container"],"container-type":[{"@container":["","normal","size",y2,R2]}],"container-named":[f$w],columns:[{columns:[aw,R2,y2,Z]}],"break-after":[{"break-after":_()}],"break-before":[{"break-before":_()}],"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:x()}],"overflow-x":[{"overflow-x":x()}],"overflow-y":[{"overflow-y":x()}],overscroll:[{overscroll:M()}],"overscroll-x":[{"overscroll-x":M()}],"overscroll-y":[{"overscroll-y":M()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:u()}],"inset-x":[{"inset-x":u()}],"inset-y":[{"inset-y":u()}],start:[{"inset-s":u(),start:u()}],end:[{"inset-e":u(),end:u()}],"inset-bs":[{"inset-bs":u()}],"inset-be":[{"inset-be":u()}],top:[{top:u()}],right:[{right:u()}],bottom:[{bottom:u()}],left:[{left:u()}],visibility:["visible","invisible","collapse"],z:[{z:[Uq,"auto",y2,R2]}],basis:[{basis:[nb,"full","auto",Z,...S()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[aw,nb,"auto","initial","none",R2]}],grow:[{grow:["",aw,y2,R2]}],shrink:[{shrink:["",aw,y2,R2]}],order:[{order:[Uq,"first","last","none",y2,R2]}],"grid-cols":[{"grid-cols":n()}],"col-start-end":[{col:e()}],"col-start":[{"col-start":X0()}],"col-end":[{"col-end":X0()}],"grid-rows":[{"grid-rows":n()}],"row-start-end":[{row:e()}],"row-start":[{"row-start":X0()}],"row-end":[{"row-end":X0()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":l()}],"auto-rows":[{"auto-rows":l()}],gap:[{gap:S()}],"gap-x":[{"gap-x":S()}],"gap-y":[{"gap-y":S()}],"justify-content":[{justify:[...P(),"normal"]}],"justify-items":[{"justify-items":[...g(),"normal"]}],"justify-self":[{"justify-self":["auto",...g()]}],"align-content":[{content:["normal",...P()]}],"align-items":[{items:[...g(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...g(),{baseline:["","last"]}]}],"place-content":[{"place-content":P()}],"place-items":[{"place-items":[...g(),"baseline"]}],"place-self":[{"place-self":["auto",...g()]}],p:[{p:S()}],px:[{px:S()}],py:[{py:S()}],ps:[{ps:S()}],pe:[{pe:S()}],pbs:[{pbs:S()}],pbe:[{pbe:S()}],pt:[{pt:S()}],pr:[{pr:S()}],pb:[{pb:S()}],pl:[{pl:S()}],m:[{m:y()}],mx:[{mx:y()}],my:[{my:y()}],ms:[{ms:y()}],me:[{me:y()}],mbs:[{mbs:y()}],mbe:[{mbe:y()}],mt:[{mt:y()}],mr:[{mr:y()}],mb:[{mb:y()}],ml:[{ml:y()}],"space-x":[{"space-x":S()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":S()}],"space-y-reverse":["space-y-reverse"],size:[{size:s()}],"inline-size":[{inline:["auto",...a()]}],"min-inline-size":[{"min-inline":["auto",...a()]}],"max-inline-size":[{"max-inline":["none",...a()]}],"block-size":[{block:["auto",...D0()]}],"min-block-size":[{"min-block":["auto",...D0()]}],"max-block-size":[{"max-block":["none",...D0()]}],w:[{w:[Z,"screen",...s()]}],"min-w":[{"min-w":[Z,"screen","none",...s()]}],"max-w":[{"max-w":[Z,"screen","none","prose",{screen:[Y]},...s()]}],h:[{h:["screen","lh",...s()]}],"min-h":[{"min-h":["screen","lh","none",...s()]}],"max-h":[{"max-h":["screen","lh",...s()]}],"font-size":[{text:["base",w,yr,FP]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[$,z$w,W$w]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",cd0,R2]}],"font-family":[{font:[G$w,K$w,Q]}],"font-features":[{"font-features":[R2]}],"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,y2,R2]}],"line-clamp":[{"line-clamp":[aw,"none",y2,Au1]}],leading:[{leading:[X,...S()]}],"list-image":[{"list-image":["none",y2,R2]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",y2,R2]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:T()}],"text-color":[{text:T()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[..._0(),"wavy"]}],"text-decoration-thickness":[{decoration:[aw,"from-font","auto",y2,FP]}],"text-decoration-color":[{decoration:T()}],"underline-offset":[{"underline-offset":[aw,"auto",y2,R2]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:S()}],"tab-size":[{tab:[Uq,y2,R2]}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",y2,R2]}],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",y2,R2]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:f0()}],"bg-repeat":[{bg:b0()}],"bg-size":[{bg:i()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},Uq,y2,R2],radial:["",y2,R2],conic:[Uq,y2,R2]},q$w,U$w]}],"bg-color":[{bg:T()}],"gradient-from-pos":[{from:u0()}],"gradient-via-pos":[{via:u0()}],"gradient-to-pos":[{to:u0()}],"gradient-from":[{from:T()}],"gradient-via":[{via:T()}],"gradient-to":[{to:T()}],rounded:[{rounded:i0()}],"rounded-s":[{"rounded-s":i0()}],"rounded-e":[{"rounded-e":i0()}],"rounded-t":[{"rounded-t":i0()}],"rounded-r":[{"rounded-r":i0()}],"rounded-b":[{"rounded-b":i0()}],"rounded-l":[{"rounded-l":i0()}],"rounded-ss":[{"rounded-ss":i0()}],"rounded-se":[{"rounded-se":i0()}],"rounded-ee":[{"rounded-ee":i0()}],"rounded-es":[{"rounded-es":i0()}],"rounded-tl":[{"rounded-tl":i0()}],"rounded-tr":[{"rounded-tr":i0()}],"rounded-br":[{"rounded-br":i0()}],"rounded-bl":[{"rounded-bl":i0()}],"border-w":[{border:k0()}],"border-w-x":[{"border-x":k0()}],"border-w-y":[{"border-y":k0()}],"border-w-s":[{"border-s":k0()}],"border-w-e":[{"border-e":k0()}],"border-w-bs":[{"border-bs":k0()}],"border-w-be":[{"border-be":k0()}],"border-w-t":[{"border-t":k0()}],"border-w-r":[{"border-r":k0()}],"border-w-b":[{"border-b":k0()}],"border-w-l":[{"border-l":k0()}],"divide-x":[{"divide-x":k0()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":k0()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[..._0(),"hidden","none"]}],"divide-style":[{divide:[..._0(),"hidden","none"]}],"border-color":[{border:T()}],"border-color-x":[{"border-x":T()}],"border-color-y":[{"border-y":T()}],"border-color-s":[{"border-s":T()}],"border-color-e":[{"border-e":T()}],"border-color-bs":[{"border-bs":T()}],"border-color-be":[{"border-be":T()}],"border-color-t":[{"border-t":T()}],"border-color-r":[{"border-r":T()}],"border-color-b":[{"border-b":T()}],"border-color-l":[{"border-l":T()}],"divide-color":[{divide:T()}],"outline-style":[{outline:[..._0(),"none","hidden"]}],"outline-offset":[{"outline-offset":[aw,y2,R2]}],"outline-w":[{outline:["",aw,yr,FP]}],"outline-color":[{outline:T()}],shadow:[{shadow:["","none",K,GX0,UX0]}],"shadow-color":[{shadow:T()}],"inset-shadow":[{"inset-shadow":["none",U,GX0,UX0]}],"inset-shadow-color":[{"inset-shadow":T()}],"ring-w":[{ring:k0()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:T()}],"ring-offset-w":[{"ring-offset":[aw,FP]}],"ring-offset-color":[{"ring-offset":T()}],"inset-ring-w":[{"inset-ring":k0()}],"inset-ring-color":[{"inset-ring":T()}],"text-shadow":[{"text-shadow":["none",G,GX0,UX0]}],"text-shadow-color":[{"text-shadow":T()}],opacity:[{opacity:[aw,y2,R2]}],"mix-blend":[{"mix-blend":[...v0(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":v0()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[aw]}],"mask-image-linear-from-pos":[{"mask-linear-from":S0()}],"mask-image-linear-to-pos":[{"mask-linear-to":S0()}],"mask-image-linear-from-color":[{"mask-linear-from":T()}],"mask-image-linear-to-color":[{"mask-linear-to":T()}],"mask-image-t-from-pos":[{"mask-t-from":S0()}],"mask-image-t-to-pos":[{"mask-t-to":S0()}],"mask-image-t-from-color":[{"mask-t-from":T()}],"mask-image-t-to-color":[{"mask-t-to":T()}],"mask-image-r-from-pos":[{"mask-r-from":S0()}],"mask-image-r-to-pos":[{"mask-r-to":S0()}],"mask-image-r-from-color":[{"mask-r-from":T()}],"mask-image-r-to-color":[{"mask-r-to":T()}],"mask-image-b-from-pos":[{"mask-b-from":S0()}],"mask-image-b-to-pos":[{"mask-b-to":S0()}],"mask-image-b-from-color":[{"mask-b-from":T()}],"mask-image-b-to-color":[{"mask-b-to":T()}],"mask-image-l-from-pos":[{"mask-l-from":S0()}],"mask-image-l-to-pos":[{"mask-l-to":S0()}],"mask-image-l-from-color":[{"mask-l-from":T()}],"mask-image-l-to-color":[{"mask-l-to":T()}],"mask-image-x-from-pos":[{"mask-x-from":S0()}],"mask-image-x-to-pos":[{"mask-x-to":S0()}],"mask-image-x-from-color":[{"mask-x-from":T()}],"mask-image-x-to-color":[{"mask-x-to":T()}],"mask-image-y-from-pos":[{"mask-y-from":S0()}],"mask-image-y-to-pos":[{"mask-y-to":S0()}],"mask-image-y-from-color":[{"mask-y-from":T()}],"mask-image-y-to-color":[{"mask-y-to":T()}],"mask-image-radial":[{"mask-radial":[y2,R2]}],"mask-image-radial-from-pos":[{"mask-radial-from":S0()}],"mask-image-radial-to-pos":[{"mask-radial-to":S0()}],"mask-image-radial-from-color":[{"mask-radial-from":T()}],"mask-image-radial-to-color":[{"mask-radial-to":T()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":O()}],"mask-image-conic-pos":[{"mask-conic":[aw]}],"mask-image-conic-from-pos":[{"mask-conic-from":S0()}],"mask-image-conic-to-pos":[{"mask-conic-to":S0()}],"mask-image-conic-from-color":[{"mask-conic-from":T()}],"mask-image-conic-to-color":[{"mask-conic-to":T()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:f0()}],"mask-repeat":[{mask:b0()}],"mask-size":[{mask:i()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",y2,R2]}],filter:[{filter:["","none",y2,R2]}],blur:[{blur:j0()}],brightness:[{brightness:[aw,y2,R2]}],contrast:[{contrast:[aw,y2,R2]}],"drop-shadow":[{"drop-shadow":["","none",q,GX0,UX0]}],"drop-shadow-color":[{"drop-shadow":T()}],grayscale:[{grayscale:["",aw,y2,R2]}],"hue-rotate":[{"hue-rotate":[aw,y2,R2]}],invert:[{invert:["",aw,y2,R2]}],saturate:[{saturate:[aw,y2,R2]}],sepia:[{sepia:["",aw,y2,R2]}],"backdrop-filter":[{"backdrop-filter":["","none",y2,R2]}],"backdrop-blur":[{"backdrop-blur":j0()}],"backdrop-brightness":[{"backdrop-brightness":[aw,y2,R2]}],"backdrop-contrast":[{"backdrop-contrast":[aw,y2,R2]}],"backdrop-grayscale":[{"backdrop-grayscale":["",aw,y2,R2]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[aw,y2,R2]}],"backdrop-invert":[{"backdrop-invert":["",aw,y2,R2]}],"backdrop-opacity":[{"backdrop-opacity":[aw,y2,R2]}],"backdrop-saturate":[{"backdrop-saturate":[aw,y2,R2]}],"backdrop-sepia":[{"backdrop-sepia":["",aw,y2,R2]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":S()}],"border-spacing-x":[{"border-spacing-x":S()}],"border-spacing-y":[{"border-spacing-y":S()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",y2,R2]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[aw,"initial",y2,R2]}],ease:[{ease:["linear","initial",k,y2,R2]}],delay:[{delay:[aw,y2,R2]}],animate:[{animate:["none",j,y2,R2]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[J,y2,R2]}],"perspective-origin":[{"perspective-origin":R()}],rotate:[{rotate:P0()}],"rotate-x":[{"rotate-x":P0()}],"rotate-y":[{"rotate-y":P0()}],"rotate-z":[{"rotate-z":P0()}],scale:[{scale:E0()}],"scale-x":[{"scale-x":E0()}],"scale-y":[{"scale-y":E0()}],"scale-z":[{"scale-z":E0()}],"scale-3d":["scale-3d"],skew:[{skew:T0()}],"skew-x":[{"skew-x":T0()}],"skew-y":[{"skew-y":T0()}],transform:[{transform:[y2,R2,"","none","gpu","cpu"]}],"transform-origin":[{origin:R()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:n0()}],"translate-x":[{"translate-x":n0()}],"translate-y":[{"translate-y":n0()}],"translate-z":[{"translate-z":n0()}],"translate-none":["translate-none"],zoom:[{zoom:[Uq,y2,R2]}],accent:[{accent:T()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:T()}],"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",y2,R2]}],"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":T()}],"scrollbar-track-color":[{"scrollbar-track":T()}],"scrollbar-gutter":[{"scrollbar-gutter":["auto","stable","both"]}],"scrollbar-w":[{scrollbar:["auto","thin","none"]}],"scroll-m":[{"scroll-m":S()}],"scroll-mx":[{"scroll-mx":S()}],"scroll-my":[{"scroll-my":S()}],"scroll-ms":[{"scroll-ms":S()}],"scroll-me":[{"scroll-me":S()}],"scroll-mbs":[{"scroll-mbs":S()}],"scroll-mbe":[{"scroll-mbe":S()}],"scroll-mt":[{"scroll-mt":S()}],"scroll-mr":[{"scroll-mr":S()}],"scroll-mb":[{"scroll-mb":S()}],"scroll-ml":[{"scroll-ml":S()}],"scroll-p":[{"scroll-p":S()}],"scroll-px":[{"scroll-px":S()}],"scroll-py":[{"scroll-py":S()}],"scroll-ps":[{"scroll-ps":S()}],"scroll-pe":[{"scroll-pe":S()}],"scroll-pbs":[{"scroll-pbs":S()}],"scroll-pbe":[{"scroll-pbe":S()}],"scroll-pt":[{"scroll-pt":S()}],"scroll-pr":[{"scroll-pr":S()}],"scroll-pb":[{"scroll-pb":S()}],"scroll-pl":[{"scroll-pl":S()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",y2,R2]}],fill:[{fill:["none",...T()]}],"stroke-w":[{stroke:[aw,yr,FP,Au1]}],stroke:[{stroke:["none",...T()]}],"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"]}},J$w=(A,{cacheSize:Q,prefix:w,experimentalParseClassName:$,extend:B={},override:X={}})=>{return zg(A,"cacheSize",Q),zg(A,"prefix",w),zg(A,"experimentalParseClassName",$),DX0(A.theme,X.theme),DX0(A.classGroups,X.classGroups),DX0(A.conflictingClassGroups,X.conflictingClassGroups),DX0(A.conflictingClassGroupModifiers,X.conflictingClassGroupModifiers),zg(A,"postfixLookupClassGroups",X.postfixLookupClassGroups),zg(A,"orderSensitiveModifiers",X.orderSensitiveModifiers),qX0(A.theme,B.theme),qX0(A.classGroups,B.classGroups),qX0(A.conflictingClassGroups,B.conflictingClassGroups),qX0(A.conflictingClassGroupModifiers,B.conflictingClassGroupModifiers),ld0(A,B,"postfixLookupClassGroups"),ld0(A,B,"orderSensitiveModifiers"),A},zg=(A,Q,w)=>{if(w!==void 0)A[Q]=w},DX0=(A,Q)=>{if(Q)for(let w in Q)zg(A,w,Q[w])},qX0=(A,Q)=>{if(Q)for(let w in Q)ld0(A,Q,w)},ld0=(A,Q,w)=>{let $=Q[w];if($!==void 0)A[w]=A[w]?A[w].concat($):$},zX0=(A,...Q)=>typeof A==="function"?em1($u1,A,...Q):em1(()=>J$w($u1(),A),...Q);var F$w=zX0({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 g2(...A){return F$w(qg(A))}var Ju1=(A)=>typeof A==="boolean"?`${A}`:A===0?"0":A,Fu1=qg,m$=(A,Q)=>(w)=>{var $;if((Q===null||Q===void 0?void 0:Q.variants)==null)return Fu1(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((W)=>{let K=w===null||w===void 0?void 0:w[W],U=X===null||X===void 0?void 0:X[W];if(K===null)return null;let G=Ju1(K)||Ju1(U);return B[W][G]}),Z=w&&Object.entries(w).reduce((W,K)=>{let[U,G]=K;if(G===void 0)return W;return W[U]=G,W},{}),H=Q===null||Q===void 0?void 0:($=Q.compoundVariants)===null||$===void 0?void 0:$.reduce((W,K)=>{let{class:U,className:G,...q}=K;return Object.entries(q).every((V)=>{let[J,F]=V;return Array.isArray(F)?F.includes({...X,...Z}[J]):{...X,...Z}[J]===F})?[...W,U,G]:W},[]);return Fu1(A,Y,H,w===null||w===void 0?void 0:w.class,w===null||w===void 0?void 0:w.className)};import{jsxDEV as dd0}from"preact/jsx-dev-runtime";var Iu1=m$("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 nd0({variant:A,title:Q,children:w,className:$}){return dd0("div",{className:g2(Iu1({variant:A}),$),role:"alert",children:[Q&&dd0("p",{className:"font-medium text-current opacity-90",children:Q},void 0,!1,void 0,this),dd0("div",{className:g2(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 I$w}from"preact/jsx-dev-runtime";var bu1=m$("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 bP({variant:A,size:Q,className:w,children:$,ssrOnClick:B,type:X="button",...Y}){return I$w("button",{type:X,className:g2(bu1({variant:A,size:Q}),w),...Y,...B&&{onclick:B},children:$},void 0,!1,void 0,this)}import{jsxDEV as b$w}from"preact/jsx-dev-runtime";var Lu1=m$("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 p9({href:A,children:Q,variant:w,size:$,external:B=!1,className:X,"aria-label":Y}){let Z=B?{target:"_blank",rel:"noopener noreferrer"}:{};return b$w("a",{href:A,className:g2(Lu1({variant:w,size:$}),X),"aria-label":Y,...Z,children:Q},void 0,!1,void 0,this)}import{jsxDEV as VX0}from"preact/jsx-dev-runtime";var ku1=m$("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"}}),L$w={sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6"};function Vg({variant:A,size:Q,className:w}){let $=L$w[Q??"md"];return VX0("button",{onclick:"toggleTheme()",type:"button",className:g2(ku1({variant:A,size:Q}),w),"aria-label":"Toggle dark mode",children:VX0("svg",{className:g2($,"transition-colors"),fill:"none",stroke:"currentColor",strokeWidth:1.6,viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:[VX0("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),VX0("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 rd0}from"preact/jsx-dev-runtime";var _u1=m$("flex flex-wrap",{variants:{orientation:{horizontal:"justify-center gap-6 items-center",vertical:"flex-col gap-2.5"}},defaultVariants:{orientation:"horizontal"}});function JX0({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 rd0("ul",{className:g2(_u1({orientation:$}),Q),children:[X.map((Y)=>rd0("li",{children:rd0("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 xw8}from"preact/jsx-dev-runtime";import{jsxDEV as hw8}from"preact/jsx-dev-runtime";import{createContext as k$w,h as _$w}from"preact";import{useContext as N$w}from"preact/hooks";var od0=k$w(null);function Jg({headCollector:A,children:Q}){return _$w(od0.Provider,{value:A},Q)}function Nu1(){return N$w(od0)}function Bw(A){let Q=Nu1();if(Q)Q.setHeadProps(A);return null}import{createContext as wXw,h as $Xw}from"preact";import{useContext as BXw}from"preact/hooks";ax0();var yi1=D1(Ci1(),1),AXw=new U$0({gfm:!0,breaks:!0}),QXw={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 Ir0(A,Q){let{imageRenderer:w}=Q??{},B=(w?new U$0({gfm:!0,breaks:!0}).use({renderer:{image({href:X,title:Y,text:Z}){return w(X,Y,Z)??!1}}}):AXw).parse(A);return B=B.replace(/<\/blockquote>\s*<p>(\u2014|--|\u2013)([\s\S]*?)<\/p>/g,`</blockquote>
|
|
5762
5762
|
<cite class="block-attribution"><span class="emdash">$1</span>$2</cite>`),yi1.default(B,QXw)}var gi1=wXw(null);function yg({imageRenderer:A,children:Q}){return $Xw(gi1.Provider,{value:A??null},Q)}function Ei1(){return BXw(gi1)}function gV(){let A=Ei1();return(Q)=>Ir0(Q,A?{imageRenderer:A}:void 0)}var XXw=/<pre><code class="language-mermaid">([\s\S]*?)<\/code><\/pre>/g,YXw={"&":"&","<":"<",">":">",""":'"',"'":"'"},ZXw=/&(?:amp|lt|gt|quot|#39);/g;function fXw(A){return A.replace(ZXw,(Q)=>YXw[Q]??Q)}function br0(A){return A.replace(XXw,(Q,w)=>{return`<div class="mermaid">${fXw(w)}</div>`})}var Ti1=/<!--\s*\.slide:\s*(.*?)\s*-->/g;function Si1(A){let Q={};for(let $ of A.matchAll(Ti1)){let B=$[1]??"";for(let Y of B.matchAll(/([\w-]+)=["']([^"']*?)["']/g)){let Z=Y[1],H=Y[2];if(Z&&H!==void 0)Q[Z]=H}let X=B.replace(/([\w-]+)=["']([^"']*?)["']/g,"").trim();if(X)for(let Y of X.matchAll(/(?:^|\s)([\w-]+)(?=\s|$)/g)){let Z=Y[1];if(Z)Q[Z]="true"}}let w=A.replace(Ti1,"").replace(/^\n+/,"").replace(/\n{3,}/g,`
|
|
5763
5763
|
|
|
5764
5764
|
`).trim();return{attributes:Q,markdown:w}}var HXw=/<!--\s*\.break\s*-->/;function mi1(A){let Q=A.split(HXw);return Q.length>1?Q:null}import{jsxDEV as Fq}from"preact/jsx-dev-runtime";var Lr0=({markdown:A,deck:Q})=>{let w=gV(),B=A.split(/^---$/gm).map((K)=>K.trim()).map((K)=>{let{attributes:U,markdown:G}=Si1(K),q=mi1(G),V;if(q)V=`<div class="slide-columns">${q.map((F)=>`<div class="slide-column">${br0(w(F.trim()))}</div>`).join("")}</div>`;else V=br0(w(G));return{attributes:U,htmlContent:V}}),X=B.some((K)=>K.htmlContent.includes('class="mermaid"')),Y=Q?.frontmatter?.title??Q?.metadata?.title,Z=Q?.frontmatter?.description??Q?.metadata?.description,H=Q?.ogImageUrl??Q?.coverImageUrl,W=B.map(({attributes:K,htmlContent:U},G)=>Fq("section",{...K,dangerouslySetInnerHTML:{__html:U}},G,!1,void 0,this));return Fq("section",{className:"presentation-section",children:[Y&&Fq(Bw,{title:Y,...Z?{description:Z}:{},...H?{ogImage:H}:{},ogType:"article"},void 0,!1,void 0,this),Fq("link",{rel:"stylesheet",href:"https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.min.css"},void 0,!1,void 0,this),Fq("div",{className:"reveal",children:Fq("div",{className:"slides",children:W},void 0,!1,void 0,this)},void 0,!1,void 0,this),Fq("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&&Fq("script",{src:"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js",defer:!0},void 0,!1,void 0,this),Fq("script",{dangerouslySetInnerHTML:{__html:`
|
|
@@ -6745,13 +6745,13 @@ ${A.map((X)=>({url:`${Q}${X.path}`,lastmod:w,changefreq:X.path==="/"?"daily":"we
|
|
|
6745
6745
|
`+B:w,Y=Rq(this.outputDir,"styles","main.css");await this.cssProcessor.process(X,Y,this.workingDir,this.outputDir,this.logger);let Z=await D4.readFile(Y,"utf-8"),H=$.length>0?$:Q;if(H.length>0){let W=H.join(`
|
|
6746
6746
|
`)+`
|
|
6747
6747
|
|
|
6748
|
-
`+Z;await D4.writeFile(Y,W,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=Rq(process.cwd(),"public");try{await D4.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await D4.readdir(A,{withFileTypes:!0});for(let w of Q){let $=Rq(A,w.name),B=Rq(this.outputDir,w.name);if(w.isDirectory())await this.copyDirectory($,B);else await D4.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=Rq(this.outputDir,B);await D4.mkdir(lbw(X),{recursive:!0}),await D4.writeFile(X,$,"utf-8"),this.logger.debug(`Wrote inline static asset: ${B}`)}))}async copyDirectory(A,Q){await D4.mkdir(Q,{recursive:!0});let w=await D4.readdir(A,{withFileTypes:!0});for(let $ of w){let B=Rq(A,$.name),X=Rq(Q,$.name);if($.isDirectory())await this.copyDirectory(B,X);else await D4.copyFile(B,X)}}}function ba0(A){return new E12(A)}f7();C0();C0();var pbw=f.object({heading:f.string(),buttonText:f.string(),buttonLink:f.string()}),ibw=f.object({blurb:f.string().optional()}),qE=f.object({title:f.string(),description:f.string(),url:f.string().optional(),copyright:f.string().optional(),logo:f.boolean().optional(),themeMode:f.enum(["light","dark"]).optional(),analyticsScript:f.string().optional(),cta:pbw.optional(),sections:f.record(f.string(),ibw).optional()});var T12=f.object({environment:f.enum(["preview","production"]),outputDir:f.string(),workingDir:f.string().optional(),sharedImagesDir:f.string().default("./dist/images"),enableContentGeneration:f.boolean().default(!1),cleanBeforeBuild:f.boolean().default(!0),siteConfig:qE,layouts:f.record(f.string(),f.any()),themeCSS:f.string().optional()}),FH8=f.object({success:f.boolean(),outputDir:f.string(),filesGenerated:f.number(),routesBuilt:f.number(),errors:f.array(f.string()).optional(),warnings:f.array(f.string()).optional()});function S12(A){let Q=A.list(),w=Q.length===0?["No routes registered for site build"]:[];return{routes:Q,warnings:w}}function m12(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"}}f7();r4();f7();k2();C0();var dbw=f.looseObject({id:f.string(),entityType:f.string(),content:f.string(),metadata:f.looseObject({slug:f.string()})}),nbw=f.looseObject({content:f.string(),metadata:f.looseObject({width:f.number().optional(),height:f.number().optional()})});async function rZ0(A,Q){let w=Q.urlGenerator??y4.getInstance();if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((O)=>rZ0(O,{...Q,urlGenerator:w})));if(typeof A!=="object")return A;let $={},B=Object.entries(A),X=await Promise.all(B.map(([,O])=>rZ0(O,{...Q,urlGenerator:w})));for(let O=0;O<B.length;O++){let R=B[O];if(R)$[R[0]]=X[O]}let Y=dbw.safeParse(A);if(!Y.success)return $;let Z=Y.data,H=Z.entityType,W=Z.metadata.slug,K=Q.pipelineContext.entityDisplay?.[H],U=K?K.label:H.charAt(0).toUpperCase()+H.slice(1),G=K?K.pluralName??K.label.toLowerCase()+"s":mK(H),q=`/${G}`,V=G.charAt(0).toUpperCase()+G.slice(1),J=Wl(Z),F=await rbw(J,Q),k=mw0(Z)??J,j=await obw(k,Q);return{...$,...Z,url:w.generateUrl(H,W),typeLabel:U,listUrl:q,listLabel:V,...F,...j&&{ogImageUrl:j}}}async function rbw(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 c12(A,Q.pipelineContext.services.entityService);if(!$)return{};return{coverImageUrl:$.url,...$.width&&{coverImageWidth:$.width},...$.height&&{coverImageHeight:$.height}}}async function obw(A,Q){if(!A)return;let w=Q.imageBuildService?.get(A);if(w)return u12(w.src,Q.siteUrl);let $=await c12(A,Q.pipelineContext.services.entityService);if(!$)return;if($.url.startsWith("data:"))return;return u12($.url,Q.siteUrl)}function u12(A,Q){if(/^https?:\/\//i.test(A)||A.startsWith("data:"))return A;if(!Q)return A;return`${Q.replace(/\/$/,"")}/${A.replace(/^\//,"")}`}async function c12(A,Q){if(!A)return;let w=await Q.getEntity({entityType:"image",id:A}),$=nbw.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 l12(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=Wl(Y);if(Z)w.add(Z);let H=mw0(Y);if(H)w.add(H)}}}catch($){Q.warn("Failed to collect image IDs for pre-resolution",{error:dA($)})}return[...w]}async function p12(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:$},H=await B.pipelineContext.services.resolveTemplateContent(X,Z);if(!H)return null;return rZ0(H,{pipelineContext:B.pipelineContext,imageBuildService:B.imageBuildService,siteUrl:B.siteUrl,urlGenerator:y4.getInstance()})}function i12(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 p12(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 m12(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 sbw}from"path";async function d12(A){let Q=A.parsedOptions.workingDir??sbw(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 n12(A){await new dZ0({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 r12(A){let Q=new iZ0(A.pipelineContext.services.entityService,A.pipelineContext.logger,A.sharedImagesDir),w=await l12(A.pipelineContext.services.entityService,A.pipelineContext.logger);if(w.length>0)await Q.resolveAll(w);return Q}async function o12(A){let Q=A.reporter?.createSub({scale:{start:85,end:95}});await A.staticSiteBuilder.build(A.buildContext,(w)=>{Q?.report(w).catch(()=>{})})}function s12(A){return{success:!0,outputDir:A.outputDir,filesGenerated:A.routesBuilt+1,routesBuilt:A.routesBuilt,...A.warnings.length>0&&{warnings:A.warnings}}}function a12(A){return{success:!1,outputDir:A.outputDir,filesGenerated:0,routesBuilt:0,errors:[A.errorMessage]}}async function t12(A){let Q=T12.parse(A.buildOptions),w=gX.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 n12({pipelineContext:A.pipelineContext,publishedOnly:Q.environment==="production"});let B=await d12({logger:A.pipelineContext.logger,parsedOptions:Q,staticSiteBuilderFactory:A.staticSiteBuilderFactory}),X=S12(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 r12({pipelineContext:A.pipelineContext,sharedImagesDir:Q.sharedImagesDir}),H=i12({routes:Y,parsedOptions:Q,buildOptions:A.buildOptions,pipelineContext:A.pipelineContext,imageBuildService:Z,siteMetadata:Q.siteConfig});return await o12({staticSiteBuilder:B,buildContext:H,reporter:w}),await w?.report({message:"Site build complete",progress:100,total:100}),s12({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}),a12({outputDir:Q.outputDir,errorMessage:X.message})}}class GH{static instance=null;static defaultStaticSiteBuilderFactory=ba0;pipelineContext;staticSiteBuilderFactory;static setDefaultStaticSiteBuilderFactory(A){GH.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,w,$,B=void 0){return GH.instance??=new GH(A,GH.defaultStaticSiteBuilderFactory,Q,w,$,B),GH.instance}static resetInstance(){GH.instance=null}static createFresh(A,Q,w,$,B,X=void 0){return new GH(A,B??GH.defaultStaticSiteBuilderFactory,Q,w,$,X)}constructor(A,Q,w,$,B,X){this.pipelineContext={logger:A,services:w,routeRegistry:$,profileService:B,entityDisplay:X},this.staticSiteBuilderFactory=Q,y4.getInstance().configure(X)}async build(A,Q){return t12({buildOptions:A,progress:Q,pipelineContext:this.pipelineContext,staticSiteBuilderFactory:this.staticSiteBuilderFactory})}}class La0{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 Sd0(()=>{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})}}}f7();function abw(A,Q){return A.map((w)=>({...w,template:w.template.includes(":")?w.template:`${Q}:${w.template}`}))}function oZ0(A,Q,w){for(let $ of A)w.register({...$,pluginId:Q,sections:$.sections?abw($.sections,Q):[]})}function e12(A,Q,w){A.messaging.subscribe("plugin:site-builder:route:register",async($)=>{try{let B=OA0.parse($.payload),{routes:X,pluginId:Y}=B;return oZ0(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=xA0.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=RA0.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=vA0.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 A22}from"fs";import{join as Q22}from"path";async function tbw(A,Q,w){let $=A.siteConfig.url??"https://example.com",B=Q.list(),X=Fa0($,A.environment);await A22.writeFile(Q22(A.outputDir,"robots.txt"),X,"utf-8"),w.info(`Generated robots.txt for ${A.environment} environment`);let Y=Ia0(B,$);await A22.writeFile(Q22(A.outputDir,"sitemap.xml"),Y,"utf-8"),w.info(`Generated sitemap.xml with ${B.length} URLs`)}function w22(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 tbw(X,w,$),{success:!0}}catch(X){return $.error("Failed to generate SEO files",X),{success:!1}}})}fA();C0();var $22=f.object({environment:f.enum(["preview","production"]).optional(),outputDir:f.string(),workingDir:f.string().optional(),enableContentGeneration:f.boolean().optional(),siteConfig:qE.optional()});f7();f7();C0();var ebw=f.object({heading:f.string(),buttonText:f.string(),buttonLink:f.string()}),ALw=f.object({blurb:f.string().optional()}),B22=f.object({title:f.string(),description:f.string(),url:f.string().optional(),copyright:f.string().optional(),logo:f.boolean().optional(),themeMode:f.enum(["light","dark"]).optional(),analyticsScript:f.string().optional(),cta:ebw.optional(),sections:f.record(f.string(),ALw).optional()});async function fs(A,Q){try{let w=await A({type:Nm,payload:void 0});if("success"in w&&w.success&&w.data){let $=B22.safeParse(w.data);if($.success)return B22.parse({...Q,...$.data})}}catch{}return Q}class ka0 extends z6{sendMessage;cfg;constructor(A,Q,w){super(A,{schema:$22,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 fs(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 H=$==="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:H},generateEntityUrl:(W,K)=>y4.getInstance().generateUrl(W,K)},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}}}C0();f7();var QLw=f.object({slot:f.enum(HF).optional().default("primary"),limit:f.number().optional()});class _a0{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 $=QLw.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((H)=>({label:H.label,href:H.href}));this.logger.debug("NavigationDataSource returning",{slot:$.slot,itemCount:X.length,items:Y});let Z={navigation:Y};return Q.parse(Z)}}f7();fA();C0();var wLw=f.object({environment:f.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function X22(A,Q){return[i6(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'.",wLw,async(w)=>{return Q(w.environment),{success:!0,message:`Site build requested${w.environment?` for ${w.environment}`:""} (debounced)`,data:{}}},{sideEffects:"external",cli:{name:"build"}})]}C0();f7();var $Lw=f.object({id:f.string(),template:f.string(),content:f.unknown().optional(),dataQuery:f.looseObject({entityType:f.string().optional(),template:f.string().optional(),query:f.looseObject({id:f.string().optional(),limit:f.number().optional(),offset:f.number().optional()}).optional()}).optional(),order:f.number().optional()}),BLw=f.object({show:f.boolean().default(!1),label:f.string().optional(),slot:f.enum(HF).default("primary"),priority:f.number().min(0).max(100).default(50)}).optional(),XLw=f.object({id:f.string(),path:f.string(),title:f.string().default(""),pageLabel:f.string().optional(),description:f.string().default(""),sections:f.array($Lw).default([]),layout:f.string().default("default"),fullscreen:f.boolean().optional(),pluginId:f.string().optional(),sourceEntityType:f.string().optional(),external:f.boolean().optional(),navigation:BLw}),Y22=f.object({previewOutputDir:f.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:f.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:f.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:f.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:qE.default({title:"Brain",description:"A knowledge management system"}),themeCSS:f.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:f.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:f.any().optional().describe("Template definitions to register"),routes:f.array(XLw).optional().describe("Routes to register"),layouts:f.record(f.string(),f.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:f.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:f.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:f.record(f.string(),f.object({label:f.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:f.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:f.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:f.boolean().optional().describe("Enable pagination for list pages"),pageSize:f.number().optional().describe("Items per page (default: 10)"),navigation:f.object({show:f.boolean().optional().describe("Show in navigation"),slot:f.enum(HF).optional().describe("Navigation slot (primary or secondary)"),priority:f.number().min(0).max(100).optional().describe("Navigation priority (0-100)")}).optional().describe("Navigation settings for this entity type")})).optional().describe("Display metadata per entity type \u2014 label, plural name, layout, pagination, navigation slot. Consulted when auto-generating routes for active entity plugins."),staticAssets:f.record(f.string(),f.string()).optional().describe("Static files to write to the output directory at build time. Keys are output paths (e.g. '/canvases/tree.js'), values are file contents as strings. Typically supplied by a SitePackage via text imports.")});var Z22={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.168",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 Na0 extends Uw{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",Z22,{...A,layouts:Q},Y22);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new nZ0(A.logger),this._slotRegistry=new bZ0,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 _a0(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=oX.getInstance(A.entityService,A.logger),e12(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)oZ0(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=GH.getInstance(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new ka0(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 La0(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(jm,async()=>{let w=await this.getInstructions();if(w)A.registerInstructions(w);return{success:!0}}),w22({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 X22(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 fs(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 fs(A.messaging.send,this.config.siteInfo);return`## Your Site
|
|
6748
|
+
`+Z;await D4.writeFile(Y,W,"utf-8")}this.logger.debug("CSS processed successfully with font imports")}async copyStaticAssets(){this.logger.debug("Copying static assets from public/ directory");let A=Rq(process.cwd(),"public");try{await D4.access(A)}catch{this.logger.debug("No public/ directory found, skipping static assets");return}let Q=await D4.readdir(A,{withFileTypes:!0});for(let w of Q){let $=Rq(A,w.name),B=Rq(this.outputDir,w.name);if(w.isDirectory())await this.copyDirectory($,B);else await D4.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=Rq(this.outputDir,B);await D4.mkdir(lbw(X),{recursive:!0}),await D4.writeFile(X,$,"utf-8"),this.logger.debug(`Wrote inline static asset: ${B}`)}))}async copyDirectory(A,Q){await D4.mkdir(Q,{recursive:!0});let w=await D4.readdir(A,{withFileTypes:!0});for(let $ of w){let B=Rq(A,$.name),X=Rq(Q,$.name);if($.isDirectory())await this.copyDirectory(B,X);else await D4.copyFile(B,X)}}}function ba0(A){return new E12(A)}f7();C0();C0();var pbw=f.object({heading:f.string(),buttonText:f.string(),buttonLink:f.string()}),ibw=f.object({blurb:f.string().optional()}),qE=f.object({title:f.string(),description:f.string(),url:f.string().optional(),copyright:f.string().optional(),logo:f.boolean().optional(),themeMode:f.enum(["light","dark"]).optional(),analyticsScript:f.string().optional(),cta:pbw.optional(),sections:f.record(f.string(),ibw).optional()});var T12=f.object({environment:f.enum(["preview","production"]),outputDir:f.string(),workingDir:f.string().optional(),sharedImagesDir:f.string().default("./dist/images"),enableContentGeneration:f.boolean().default(!1),cleanBeforeBuild:f.boolean().default(!0),siteConfig:qE,layouts:f.record(f.string(),f.any()),themeCSS:f.string().optional()}),FH8=f.object({success:f.boolean(),outputDir:f.string(),filesGenerated:f.number(),routesBuilt:f.number(),errors:f.array(f.string()).optional(),warnings:f.array(f.string()).optional()});function S12(A){let Q=A.list(),w=Q.length===0?["No routes registered for site build"]:[];return{routes:Q,warnings:w}}function m12(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"}}f7();r4();f7();k2();C0();var dbw=f.looseObject({id:f.string(),entityType:f.string(),content:f.string(),metadata:f.looseObject({slug:f.string()})}),nbw=f.looseObject({content:f.string(),metadata:f.looseObject({width:f.number().optional(),height:f.number().optional()})});async function rZ0(A,Q){let w=Q.urlGenerator??y4.getInstance();if(A===null||A===void 0)return A;if(Array.isArray(A))return Promise.all(A.map((O)=>rZ0(O,{...Q,urlGenerator:w})));if(typeof A!=="object")return A;let $={},B=Object.entries(A),X=await Promise.all(B.map(([,O])=>rZ0(O,{...Q,urlGenerator:w})));for(let O=0;O<B.length;O++){let R=B[O];if(R)$[R[0]]=X[O]}let Y=dbw.safeParse(A);if(!Y.success)return $;let Z=Y.data,H=Z.entityType,W=Z.metadata.slug,K=Q.pipelineContext.entityDisplay?.[H],U=K?K.label:H.charAt(0).toUpperCase()+H.slice(1),G=K?K.pluralName??K.label.toLowerCase()+"s":mK(H),q=`/${G}`,V=G.charAt(0).toUpperCase()+G.slice(1),J=Wl(Z),F=await rbw(J,Q),k=mw0(Z)??J,j=await obw(k,Q);return{...$,...Z,url:w.generateUrl(H,W),typeLabel:U,listUrl:q,listLabel:V,...F,...j&&{ogImageUrl:j}}}async function rbw(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 c12(A,Q.pipelineContext.services.entityService);if(!$)return{};return{coverImageUrl:$.url,...$.width&&{coverImageWidth:$.width},...$.height&&{coverImageHeight:$.height}}}async function obw(A,Q){if(!A)return;let w=Q.imageBuildService?.get(A);if(w)return u12(w.src,Q.siteUrl);let $=await c12(A,Q.pipelineContext.services.entityService);if(!$)return;if($.url.startsWith("data:"))return;return u12($.url,Q.siteUrl)}function u12(A,Q){if(/^https?:\/\//i.test(A)||A.startsWith("data:"))return A;if(!Q)return A;return`${Q.replace(/\/$/,"")}/${A.replace(/^\//,"")}`}async function c12(A,Q){if(!A)return;let w=await Q.getEntity({entityType:"image",id:A}),$=nbw.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 l12(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=Wl(Y);if(Z)w.add(Z);let H=mw0(Y);if(H)w.add(H)}}}catch($){Q.warn("Failed to collect image IDs for pre-resolution",{error:dA($)})}return[...w]}async function p12(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:$},H=await B.pipelineContext.services.resolveTemplateContent(X,Z);if(!H)return null;return rZ0(H,{pipelineContext:B.pipelineContext,imageBuildService:B.imageBuildService,siteUrl:B.siteUrl,urlGenerator:y4.getInstance()})}function i12(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 p12(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 m12(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 sbw}from"path";async function d12(A){let Q=A.parsedOptions.workingDir??sbw(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 n12(A){await new dZ0({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 r12(A){let Q=new iZ0(A.pipelineContext.services.entityService,A.pipelineContext.logger,A.sharedImagesDir),w=await l12(A.pipelineContext.services.entityService,A.pipelineContext.logger);if(w.length>0)await Q.resolveAll(w);return Q}async function o12(A){let Q=A.reporter?.createSub({scale:{start:85,end:95}});await A.staticSiteBuilder.build(A.buildContext,(w)=>{Q?.report(w).catch(()=>{})})}function s12(A){return{success:!0,outputDir:A.outputDir,filesGenerated:A.routesBuilt+1,routesBuilt:A.routesBuilt,...A.warnings.length>0&&{warnings:A.warnings}}}function a12(A){return{success:!1,outputDir:A.outputDir,filesGenerated:0,routesBuilt:0,errors:[A.errorMessage]}}async function t12(A){let Q=T12.parse(A.buildOptions),w=gX.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 n12({pipelineContext:A.pipelineContext,publishedOnly:Q.environment==="production"});let B=await d12({logger:A.pipelineContext.logger,parsedOptions:Q,staticSiteBuilderFactory:A.staticSiteBuilderFactory}),X=S12(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 r12({pipelineContext:A.pipelineContext,sharedImagesDir:Q.sharedImagesDir}),H=i12({routes:Y,parsedOptions:Q,buildOptions:A.buildOptions,pipelineContext:A.pipelineContext,imageBuildService:Z,siteMetadata:Q.siteConfig});return await o12({staticSiteBuilder:B,buildContext:H,reporter:w}),await w?.report({message:"Site build complete",progress:100,total:100}),s12({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}),a12({outputDir:Q.outputDir,errorMessage:X.message})}}class GH{static instance=null;static defaultStaticSiteBuilderFactory=ba0;pipelineContext;staticSiteBuilderFactory;static setDefaultStaticSiteBuilderFactory(A){GH.defaultStaticSiteBuilderFactory=A}static getInstance(A,Q,w,$,B=void 0){return GH.instance??=new GH(A,GH.defaultStaticSiteBuilderFactory,Q,w,$,B),GH.instance}static resetInstance(){GH.instance=null}static createFresh(A,Q,w,$,B,X=void 0){return new GH(A,B??GH.defaultStaticSiteBuilderFactory,Q,w,$,X)}constructor(A,Q,w,$,B,X){this.pipelineContext={logger:A,services:w,routeRegistry:$,profileService:B,entityDisplay:X},this.staticSiteBuilderFactory=Q,y4.getInstance().configure(X)}async build(A,Q){return t12({buildOptions:A,progress:Q,pipelineContext:this.pipelineContext,staticSiteBuilderFactory:this.staticSiteBuilderFactory})}}class La0{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 Sd0(()=>{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})}}}f7();function abw(A,Q){return A.map((w)=>({...w,template:w.template.includes(":")?w.template:`${Q}:${w.template}`}))}function oZ0(A,Q,w){for(let $ of A)w.register({...$,pluginId:Q,sections:$.sections?abw($.sections,Q):[]})}function e12(A,Q,w){A.messaging.subscribe("plugin:site-builder:route:register",async($)=>{try{let B=OA0.parse($.payload),{routes:X,pluginId:Y}=B;return oZ0(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=xA0.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=RA0.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=vA0.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 A22}from"fs";import{join as Q22}from"path";async function tbw(A,Q,w){let $=A.siteConfig.url??"https://example.com",B=Q.list(),X=Fa0($,A.environment);await A22.writeFile(Q22(A.outputDir,"robots.txt"),X,"utf-8"),w.info(`Generated robots.txt for ${A.environment} environment`);let Y=Ia0(B,$);await A22.writeFile(Q22(A.outputDir,"sitemap.xml"),Y,"utf-8"),w.info(`Generated sitemap.xml with ${B.length} URLs`)}function w22(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 tbw(X,w,$),{success:!0}}catch(X){return $.error("Failed to generate SEO files",X),{success:!1}}})}fA();C0();var $22=f.object({environment:f.enum(["preview","production"]).optional(),outputDir:f.string(),workingDir:f.string().optional(),enableContentGeneration:f.boolean().optional(),siteConfig:qE.optional()});f7();f7();C0();var ebw=f.object({heading:f.string(),buttonText:f.string(),buttonLink:f.string()}),ALw=f.object({blurb:f.string().optional()}),B22=f.object({title:f.string(),description:f.string(),url:f.string().optional(),copyright:f.string().optional(),logo:f.boolean().optional(),themeMode:f.enum(["light","dark"]).optional(),analyticsScript:f.string().optional(),cta:ebw.optional(),sections:f.record(f.string(),ALw).optional()});async function fs(A,Q){try{let w=await A({type:Nm,payload:void 0});if("success"in w&&w.success&&w.data){let $=B22.safeParse(w.data);if($.success)return B22.parse({...Q,...$.data})}}catch{}return Q}class ka0 extends z6{sendMessage;cfg;constructor(A,Q,w){super(A,{schema:$22,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 fs(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 H=$==="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:H},generateEntityUrl:(W,K)=>y4.getInstance().generateUrl(W,K)},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}}}C0();f7();var QLw=f.object({slot:f.enum(HF).optional().default("primary"),limit:f.number().optional()});class _a0{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 $=QLw.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((H)=>({label:H.label,href:H.href}));this.logger.debug("NavigationDataSource returning",{slot:$.slot,itemCount:X.length,items:Y});let Z={navigation:Y};return Q.parse(Z)}}f7();fA();C0();var wLw=f.object({environment:f.enum(["preview","production"]).optional().describe("Build environment (defaults to production, or preview if configured)")});function X22(A,Q){return[i6(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'.",wLw,async(w)=>{return Q(w.environment),{success:!0,message:`Site build requested${w.environment?` for ${w.environment}`:""} (debounced)`,data:{}}},{sideEffects:"external",cli:{name:"build"}})]}C0();f7();var $Lw=f.object({id:f.string(),template:f.string(),content:f.unknown().optional(),dataQuery:f.looseObject({entityType:f.string().optional(),template:f.string().optional(),query:f.looseObject({id:f.string().optional(),limit:f.number().optional(),offset:f.number().optional()}).optional()}).optional(),order:f.number().optional()}),BLw=f.object({show:f.boolean().default(!1),label:f.string().optional(),slot:f.enum(HF).default("primary"),priority:f.number().min(0).max(100).default(50)}).optional(),XLw=f.object({id:f.string(),path:f.string(),title:f.string().default(""),pageLabel:f.string().optional(),description:f.string().default(""),sections:f.array($Lw).default([]),layout:f.string().default("default"),fullscreen:f.boolean().optional(),pluginId:f.string().optional(),sourceEntityType:f.string().optional(),external:f.boolean().optional(),navigation:BLw}),Y22=f.object({previewOutputDir:f.string().describe("Output directory for preview builds").default("./dist/site-preview"),productionOutputDir:f.string().describe("Output directory for production builds").default("./dist/site-production"),sharedImagesDir:f.string().describe("Shared directory for optimized images (used by both preview and production)").default("./dist/images"),workingDir:f.string().optional().describe("Working directory for builds").default("./.preact-work"),siteInfo:qE.default({title:"Brain",description:"A knowledge management system"}),themeCSS:f.string().describe("Custom CSS theme overrides to inject into builds").optional(),analyticsScript:f.string().describe("Analytics tracking script to inject into page head (e.g., Cloudflare Web Analytics)").optional(),templates:f.any().optional().describe("Template definitions to register"),routes:f.array(XLw).optional().describe("Routes to register"),layouts:f.record(f.string(),f.any()).optional().describe("Layout components (at least 'default' required)"),autoRebuild:f.boolean().default(!0).describe("Automatically rebuild site when content changes"),rebuildDebounce:f.number().min(100).describe("Debounce time in ms before triggering site rebuild after content changes").default(5000),entityDisplay:f.record(f.string(),f.object({label:f.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:f.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')"),layout:f.string().optional().describe("Layout name for this entity type's generated routes (defaults to 'default')"),paginate:f.boolean().optional().describe("Enable pagination for list pages"),pageSize:f.number().optional().describe("Items per page (default: 10)"),navigation:f.object({show:f.boolean().optional().describe("Show in navigation"),slot:f.enum(HF).optional().describe("Navigation slot (primary or secondary)"),priority:f.number().min(0).max(100).optional().describe("Navigation priority (0-100)")}).optional().describe("Navigation settings for this entity type")})).optional().describe("Display metadata per entity type \u2014 label, plural name, layout, pagination, navigation slot. Consulted when auto-generating routes for active entity plugins."),staticAssets:f.record(f.string(),f.string()).optional().describe("Static files to write to the output directory at build time. Keys are output paths (e.g. '/canvases/tree.js'), values are file contents as strings. Typically supplied by a SitePackage via text imports.")});var Z22={name:"@brains/site-builder-plugin",version:"0.2.0-alpha.169",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 Na0 extends Uw{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",Z22,{...A,layouts:Q},Y22);this.layouts=Q}async onRegister(A){if(this.pluginContext=A,this._routeRegistry=new nZ0(A.logger),this._slotRegistry=new bZ0,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 _a0(this._routeRegistry,A.logger.child("NavigationDataSource"))),this.profileService=oX.getInstance(A.entityService,A.logger),e12(A,this._routeRegistry,this.logger),this.config.templates)A.templates.register(this.config.templates);if(this.config.routes)oZ0(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=GH.getInstance(A.logger.child("SiteBuilder"),Q,this.routeRegistry,this.profileService,this.config.entityDisplay),A.jobs.registerHandler("site-build",new ka0(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 La0(this.config,A,this.id,this.logger),this.config.autoRebuild)this.logger.debug("Auto-rebuild enabled"),this.rebuildManager.setupAutoRebuild();A.messaging.subscribe(jm,async()=>{let w=await this.getInstructions();if(w)A.registerInstructions(w);return{success:!0}}),w22({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 X22(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 fs(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 fs(A.messaging.send,this.config.siteInfo);return`## Your Site
|
|
6749
6749
|
${[`**Title:** ${w.title}`,`**Description:** ${w.description}`,A.domain&&`**Domain:** ${A.domain}`,A.siteUrl&&`**URL:** ${A.siteUrl}`].filter(Boolean).join(`
|
|
6750
6750
|
`)}
|
|
6751
6751
|
|
|
6752
6752
|
## Site Builder Actions
|
|
6753
6753
|
- When the user asks to build, rebuild, publish, or build the website/site again, call \`site-builder_build-site\` immediately.
|
|
6754
|
-
- Every repeated build request requires a fresh \`site-builder_build-site\` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.`}async onShutdown(){this.logger.debug("Shutting down site-builder plugin"),this.rebuildManager?.dispose(),GH.resetInstance(),this.logger.debug("Cleaned up all event subscriptions")}}function QM(A={}){return new Na0(A)}fA();fA();C0();var ja0=f.object({routeId:f.string(),sectionId:f.string()}),ZLw=f.object({routeId:f.string(),sectionId:f.string()}),Hs=TQ.extend({entityType:f.literal("site-content"),template:f.string().optional(),content:f.string(),metadata:ZLw});fA();class f22 extends r2{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:Hs,frontmatterSchema:ja0})}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 Pa0=new f22;C0();var sZ0=f.object({routeId:f.string().optional().describe("Optional: specific route filter"),sectionId:f.string().optional().describe("Optional: specific section filter"),dryRun:f.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:f.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),fK8=f.object({jobs:f.array(f.object({jobId:f.string(),routeId:f.string(),sectionId:f.string()})),totalSections:f.number(),queuedSections:f.number(),skippedSections:f.number().optional(),batchId:f.string().optional()});C0();var fLw=f.looseObject({id:f.string(),template:f.string().optional(),content:f.unknown().optional()}),HLw=f.looseObject({id:f.string(),title:f.string().optional(),description:f.string().optional(),sections:f.array(fLw)}),WLw=f.array(HLw);class Ma0{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=WLw.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((K)=>K.id===A.routeId),X.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let K of X)for(let U of K.sections){if(A.sectionId&&U.id!==A.sectionId)continue;if(U.content){$.debug("Section has static content, skipping",{routeId:K.id,sectionId:U.id});continue}if(U.template){let G=this.context.templates.getCapabilities(U.template);if(!G){$.warn("Template not found, skipping section",{routeId:K.id,sectionId:U.id,templateName:U.template});continue}if(!G.canGenerate){$.debug("Template doesn't support generation, skipping",{routeId:K.id,sectionId:U.id,templateName:U.template,capabilities:G});continue}}else{$.debug("Section has no template, skipping",{routeId:K.id,sectionId:U.id});continue}if(!A.force&&!A.dryRun){let G=`${K.id}:${U.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:G})){$.debug("Content already exists, skipping",{routeId:K.id,sectionId:U.id});continue}}Y.push({route:K,section:U})}let Z=Y.length;if(A.dryRun)return{jobs:[],totalSections:Z,queuedSections:Z,batchId:`dry-run-${Date.now()}`};let H=[],W=[];for(let{route:K,section:U}of Y){let G=`${K.id}:${U.id}`,q=U.template,V={routeId:K.id,sectionId:U.id,entityId:G,entityType:"site-content",templateName:q,context:{prompt:typeof U.content==="string"?U.content:void 0,data:{routeId:K.id,sectionId:U.id,routeTitle:K.title,routeDescription:K.description,sectionContent:U.content},conversationId:"system"},siteConfig:Q};W.push({type:"shell:content-generation",data:V})}if(W.length>0){let K=this.createJobOptions(w,"site:content-generation"),U=await this.context.jobs.enqueueBatch(W,K);for(let G=0;G<Y.length;G++){let q=Y[G];if(q)H.push({jobId:`${U}-${G}`,routeId:q.route.id,sectionId:q.section.id})}return{jobs:H,totalSections:Z,queuedSections:H.length,batchId:U}}return{jobs:[],totalSections:Z,queuedSections:0,batchId:`empty-${Date.now()}`}}}class Oa0{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new Ma0(A)}async generateContent(A,Q){let w=sZ0.parse(A);return this.operations.generate(w,this.siteConfig,Q)}}f7();C0();var KLw=f.object({namespace:f.string(),sections:f.record(f.string(),f.any())}),H22=f.custom((A)=>KLw.safeParse(A).success),xa0=f.object({definitions:f.union([H22,f.array(H22)]).optional()});fA();function W22(A,Q){return[i6(Q,"generate","Generate content for all routes, a specific route, or a specific section",sZ0,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 K22={name:"@brains/site-content",version:"0.2.0-alpha.168",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 Ra0 extends Uw{siteContentService;constructor(A={}){super("site-content",K22,A,xa0)}async onRegister(A){A.entities.register("site-content",Hs,Pa0);for(let Q of GI(this.config.definitions))A.templates.register(JF(Q),Q.namespace);this.siteContentService=new Oa0(A)}async getTools(){return W22(()=>this.siteContentService,this.id)}}function wM(A={}){return new Ra0(A)}fA();f7();fA();C0();f7();var GLw=f.object({}),DLw=f.object({}),Ws=TQ.extend({id:f.literal("site-info"),entityType:f.literal("site-info"),metadata:DLw});var zE=hF0.omit({url:!0,analyticsScript:!0});fA();C0();var qLw=f.record(f.string(),f.unknown());class vq extends r2{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:Ws,frontmatterSchema:zE,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=zE.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("",qLw.parse(Q))}}class hq{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,w){return hq.instance??=new hq(A,Q,w),hq.instance}static resetInstance(){hq.instance=null}static createFresh(A,Q,w){return new hq(A,Q,w)}constructor(A,Q,w){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new vq;let $=hq.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}}C0();var zLw=new vq,VLw=f.looseObject({platform:f.string(),url:f.string(),label:f.string().optional()}).transform((A)=>({platform:A.platform,url:A.url,...A.label!==void 0?{label:A.label}:{}})),JLw=f.looseObject({socialLinks:f.array(VLw).optional()});class aZ0{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?zLw.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 H=JLw.safeParse(Z.metadata);X=H.success?H.data.socialLinks:void 0}}catch{}let Y={...B,socialLinks:X,copyright:B.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var U22={name:"@brains/site-info",version:"0.2.0-alpha.168",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 ILw=new vq,bLw="site-info";class va0 extends fw{entityType=bLw;schema=Ws;adapter=ILw;defaultSiteInfo;constructor(A){super("site-info",U22,{},o7);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new aZ0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=hq.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(Nm,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:jm,payload:B,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function $M(A){return new va0(A)}var LLw=new vq;async function Ks(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 LLw.parseSiteInfoBody(w.content)}function G22(A,Q){let w=A.metadata.publishedAt??A.created,$=Q.metadata.publishedAt??Q.created;return new Date($).getTime()-new Date(w).getTime()}async function tZ0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(G22).slice(0,Q.count).map(Q.parse)}function ha0(A){if(!A)throw Error("CTA not configured in site-info");return A}C0();var D22=f.object({label:f.string(),href:f.string(),priority:f.number()}),kLw=f.object({primary:f.array(D22),secondary:f.array(D22)}),_Lw=f.object({platform:f.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:f.string().describe("Profile or contact URL"),label:f.string().optional().describe("Optional display label")}),NLw=zE.extend({navigation:kLw,copyright:f.string(),socialLinks:f.array(_Lw).optional().describe("Social media links from profile entity")});fA();DH();FE();C0();var Ca0=f.object({defaultPrompt:f.string().default("Write a blog post about my recent work and insights"),paginate:f.boolean().default(!0),pageSize:f.number().default(10)});fA();Q$();k2();C0();var OLw=f.object({prompt:f.string().optional(),title:f.string().optional(),content:f.string().optional(),excerpt:f.string().optional(),coverImageId:f.string().optional(),seriesName:f.string().optional(),seriesIndex:f.number().optional(),skipAi:f.boolean().optional()}),TU8=wf.extend({title:f.string().optional(),slug:f.string().optional()});class ya0 extends l4{constructor(A,Q){super(A,Q,{schema:OLw,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:w,coverImageId:$,seriesName:B,seriesIndex:X,skipAi:Y}=A,{title:Z,content:H,excerpt:W}=A;if(Y){if(!Z)this.failEarly("Title is required when skipAi is true");H=H??`## Introduction
|
|
6754
|
+
- Every repeated build request requires a fresh \`site-builder_build-site\` call. Do not say a build was started, queued, or requested unless this turn invoked the tool.`}async onShutdown(){this.logger.debug("Shutting down site-builder plugin"),this.rebuildManager?.dispose(),GH.resetInstance(),this.logger.debug("Cleaned up all event subscriptions")}}function QM(A={}){return new Na0(A)}fA();fA();C0();var ja0=f.object({routeId:f.string(),sectionId:f.string()}),ZLw=f.object({routeId:f.string(),sectionId:f.string()}),Hs=TQ.extend({entityType:f.literal("site-content"),template:f.string().optional(),content:f.string(),metadata:ZLw});fA();class f22 extends r2{constructor(){super({entityType:"site-content",purpose:"A content section bound to a route on the published site.",schema:Hs,frontmatterSchema:ja0})}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 Pa0=new f22;C0();var sZ0=f.object({routeId:f.string().optional().describe("Optional: specific route filter"),sectionId:f.string().optional().describe("Optional: specific section filter"),dryRun:f.boolean().optional().default(!1).describe("Optional: preview changes without executing"),force:f.boolean().optional().default(!1).describe("Force regeneration even if content exists")}),fK8=f.object({jobs:f.array(f.object({jobId:f.string(),routeId:f.string(),sectionId:f.string()})),totalSections:f.number(),queuedSections:f.number(),skippedSections:f.number().optional(),batchId:f.string().optional()});C0();var fLw=f.looseObject({id:f.string(),template:f.string().optional(),content:f.unknown().optional()}),HLw=f.looseObject({id:f.string(),title:f.string().optional(),description:f.string().optional(),sections:f.array(fLw)}),WLw=f.array(HLw);class Ma0{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=WLw.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((K)=>K.id===A.routeId),X.length===0)throw Error(`Route not found: ${A.routeId}`)}let Y=[];for(let K of X)for(let U of K.sections){if(A.sectionId&&U.id!==A.sectionId)continue;if(U.content){$.debug("Section has static content, skipping",{routeId:K.id,sectionId:U.id});continue}if(U.template){let G=this.context.templates.getCapabilities(U.template);if(!G){$.warn("Template not found, skipping section",{routeId:K.id,sectionId:U.id,templateName:U.template});continue}if(!G.canGenerate){$.debug("Template doesn't support generation, skipping",{routeId:K.id,sectionId:U.id,templateName:U.template,capabilities:G});continue}}else{$.debug("Section has no template, skipping",{routeId:K.id,sectionId:U.id});continue}if(!A.force&&!A.dryRun){let G=`${K.id}:${U.id}`;if(await this.context.entityService.getEntity({entityType:"site-content",id:G})){$.debug("Content already exists, skipping",{routeId:K.id,sectionId:U.id});continue}}Y.push({route:K,section:U})}let Z=Y.length;if(A.dryRun)return{jobs:[],totalSections:Z,queuedSections:Z,batchId:`dry-run-${Date.now()}`};let H=[],W=[];for(let{route:K,section:U}of Y){let G=`${K.id}:${U.id}`,q=U.template,V={routeId:K.id,sectionId:U.id,entityId:G,entityType:"site-content",templateName:q,context:{prompt:typeof U.content==="string"?U.content:void 0,data:{routeId:K.id,sectionId:U.id,routeTitle:K.title,routeDescription:K.description,sectionContent:U.content},conversationId:"system"},siteConfig:Q};W.push({type:"shell:content-generation",data:V})}if(W.length>0){let K=this.createJobOptions(w,"site:content-generation"),U=await this.context.jobs.enqueueBatch(W,K);for(let G=0;G<Y.length;G++){let q=Y[G];if(q)H.push({jobId:`${U}-${G}`,routeId:q.route.id,sectionId:q.section.id})}return{jobs:H,totalSections:Z,queuedSections:H.length,batchId:U}}return{jobs:[],totalSections:Z,queuedSections:0,batchId:`empty-${Date.now()}`}}}class Oa0{siteConfig;operations;constructor(A,Q){this.siteConfig=Q,this.operations=new Ma0(A)}async generateContent(A,Q){let w=sZ0.parse(A);return this.operations.generate(w,this.siteConfig,Q)}}f7();C0();var KLw=f.object({namespace:f.string(),sections:f.record(f.string(),f.any())}),H22=f.custom((A)=>KLw.safeParse(A).success),xa0=f.object({definitions:f.union([H22,f.array(H22)]).optional()});fA();function W22(A,Q){return[i6(Q,"generate","Generate content for all routes, a specific route, or a specific section",sZ0,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 K22={name:"@brains/site-content",version:"0.2.0-alpha.169",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 Ra0 extends Uw{siteContentService;constructor(A={}){super("site-content",K22,A,xa0)}async onRegister(A){A.entities.register("site-content",Hs,Pa0);for(let Q of GI(this.config.definitions))A.templates.register(JF(Q),Q.namespace);this.siteContentService=new Oa0(A)}async getTools(){return W22(()=>this.siteContentService,this.id)}}function wM(A={}){return new Ra0(A)}fA();f7();fA();C0();f7();var GLw=f.object({}),DLw=f.object({}),Ws=TQ.extend({id:f.literal("site-info"),entityType:f.literal("site-info"),metadata:DLw});var zE=hF0.omit({url:!0,analyticsScript:!0});fA();C0();var qLw=f.record(f.string(),f.unknown());class vq extends r2{constructor(){super({entityType:"site-info",purpose:"Singleton configuration describing the published site.",schema:Ws,frontmatterSchema:zE,isSingleton:!0,hasBody:!1})}createSiteInfoContent(A){let Q=zE.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("",qLw.parse(Q))}}class hq{static instance=null;logger;entityService;adapter;defaultSiteInfo;static getDefaultSiteInfo(){return{title:"Brain",description:"A knowledge management system"}}static getInstance(A,Q,w){return hq.instance??=new hq(A,Q,w),hq.instance}static resetInstance(){hq.instance=null}static createFresh(A,Q,w){return new hq(A,Q,w)}constructor(A,Q,w){this.entityService=A,this.logger=Q.child("SiteInfoService"),this.adapter=new vq;let $=hq.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}}C0();var zLw=new vq,VLw=f.looseObject({platform:f.string(),url:f.string(),label:f.string().optional()}).transform((A)=>({platform:A.platform,url:A.url,...A.label!==void 0?{label:A.label}:{}})),JLw=f.looseObject({socialLinks:f.array(VLw).optional()});class aZ0{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?zLw.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 H=JLw.safeParse(Z.metadata);X=H.success?H.data.socialLinks:void 0}}catch{}let Y={...B,socialLinks:X,copyright:B.copyright??"Powered by Rizom"};return this.logger.debug("SiteInfoDataSource returning",{title:Y.title,hasSocialLinks:!!Y.socialLinks}),Q.parse(Y)}}var U22={name:"@brains/site-info",version:"0.2.0-alpha.169",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 ILw=new vq,bLw="site-info";class va0 extends fw{entityType=bLw;schema=Ws;adapter=ILw;defaultSiteInfo;constructor(A){super("site-info",U22,{},o7);this.defaultSiteInfo=A?.siteInfo??{}}getEntityTypeConfig(){return{embeddable:!1}}getDataSources(){return[new aZ0(this.logger.child("SiteInfoDataSource"))]}async onRegister(A){let Q=hq.createFresh(A.entityService,this.logger,this.defaultSiteInfo);A.messaging.subscribe(Nm,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:jm,payload:B,broadcast:!0})}return{success:!0}}),A.messaging.subscribe("sync:initial:completed",async()=>{return await Q.initialize(),{success:!0}})}}function $M(A){return new va0(A)}var LLw=new vq;async function Ks(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 LLw.parseSiteInfoBody(w.content)}function G22(A,Q){let w=A.metadata.publishedAt??A.created,$=Q.metadata.publishedAt??Q.created;return new Date($).getTime()-new Date(w).getTime()}async function tZ0(A,Q){return(await A.listEntities({entityType:Q.entityType,options:{limit:20}})).sort(G22).slice(0,Q.count).map(Q.parse)}function ha0(A){if(!A)throw Error("CTA not configured in site-info");return A}C0();var D22=f.object({label:f.string(),href:f.string(),priority:f.number()}),kLw=f.object({primary:f.array(D22),secondary:f.array(D22)}),_Lw=f.object({platform:f.enum(["github","instagram","linkedin","email","website"]).describe("Social media platform"),url:f.string().describe("Profile or contact URL"),label:f.string().optional().describe("Optional display label")}),NLw=zE.extend({navigation:kLw,copyright:f.string(),socialLinks:f.array(_Lw).optional().describe("Social media links from profile entity")});fA();DH();FE();C0();var Ca0=f.object({defaultPrompt:f.string().default("Write a blog post about my recent work and insights"),paginate:f.boolean().default(!0),pageSize:f.number().default(10)});fA();Q$();k2();C0();var OLw=f.object({prompt:f.string().optional(),title:f.string().optional(),content:f.string().optional(),excerpt:f.string().optional(),coverImageId:f.string().optional(),seriesName:f.string().optional(),seriesIndex:f.number().optional(),skipAi:f.boolean().optional()}),TU8=wf.extend({title:f.string().optional(),slug:f.string().optional()});class ya0 extends l4{constructor(A,Q){super(A,Q,{schema:OLw,jobTypeName:"blog-generation",entityType:"post"})}async generate(A,Q){let{prompt:w,coverImageId:$,seriesName:B,seriesIndex:X,skipAi:Y}=A,{title:Z,content:H,excerpt:W}=A;if(Y){if(!Z)this.failEarly("Title is required when skipAi is true");H=H??`## Introduction
|
|
6755
6755
|
|
|
6756
6756
|
Add your introduction here.
|
|
6757
6757
|
|
|
@@ -6971,7 +6971,7 @@ ${w.content}`,templateName:"blog:excerpt"})})}fA();FE();DH();function eLw(A){let
|
|
|
6971
6971
|
letter-spacing: 0.02em;
|
|
6972
6972
|
}
|
|
6973
6973
|
.printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
|
|
6974
|
-
`}},void 0,!1,void 0,this),q4("header",{className:"printable-hero",children:[q4("div",{className:"printable-masthead",children:Q.brandLabel&&q4("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),q4("div",{children:[q4("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&q4("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),q4("div",{className:"printable-meta",children:[Q.author&&q4("span",{children:["By ",Q.author]},void 0,!0,void 0,this),w&&q4("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&&q4("figure",{className:"printable-cover-wrap",children:q4("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),q4(i9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&q4("footer",{className:"printable-footer",children:[q4("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&q4("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 ykw=26214400,gkw=60000;class da0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??HG}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==wf0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=Ekw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await Rkw(Ckw(hkw(),"brain-blog-printable-"));try{let B=await zH({outputDir:$,mediaPath:`/_media/printable/post/${Q.id}`,template:y22,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await VH({rootDir:$});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:ykw,timeoutMs:gkw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${Tkw(Q)}-printable.pdf`}}finally{await X.close()}}finally{await vkw($,{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}=p6(A.content),w=y8.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 Ekw(A,Q={}){let{frontmatter:w,content:$}=p6(A.content),B=y8.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 Tkw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}import{mkdtemp as lkw,rm as pkw}from"fs/promises";import{tmpdir as ikw}from"os";import{join as dkw}from"path";K7();k2();DH();C0();import{jsxDEV as ckw}from"preact/jsx-dev-runtime";var Vs="og-image",Skw="blog:og-image",g22=f.object({title:f.string().min(1),excerpt:f.string().optional(),author:f.string().optional(),publishedAt:f.string().optional(),brandLabel:f.string().optional(),coverImageUrl:f.string().optional()}),E22={name:Skw,pluginId:"blog",schema:g22,renderers:{image:ukw}};function mkw(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 ukw(A){let Q=g22.parse(A);return ckw(EV,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:mkw(Q.publishedAt)},void 0,!1,void 0,this)}var nkw={width:1200,height:630},rkw=60000;class na0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??zs}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==Vs)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=okw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await lkw(dkw(ikw(),"brain-blog-og-image-"));try{let B=await zH({outputDir:$,mediaPath:`/_media/og/post/${Q.id}`,template:E22,format:"image",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await VH({rootDir:$});try{return{type:"image",data:await this.screenshotPng(X.urlFor(B.urlPath),nkw,{timeoutMs:rkw,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${skw(Q)}-og.png`}}finally{await X.close()}}finally{await pkw($,{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}=p6(A.content),w=y8.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 okw(A,Q={}){let{frontmatter:w}=p6(A.content),$=y8.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 skw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}var T22={name:"@brains/blog",version:"0.2.0-alpha.168",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 ra0 extends fw{entityType=eV.entityType;schema=VE;adapter=eV;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",T22,A,Ca0)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new ya0(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return I22()}getDataSources(){return[new Ea0(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (u22(),m22));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),b22(A,this.logger),L22(A,this.logger),_22(A,this.logger),N22(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",wf0,new da0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",Vs,new na0(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=NB.getInstance().register(ma0()),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:Vs,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 oa0(A={}){return new ra0(A)}DH();FE();fA();C0();H5();fA();C0();var WG=f.object({title:f.string(),slug:f.string(),coverImageId:f.string().optional()}),ekw=f.object({title:f.string(),slug:f.string()}),A_w=f.object({title:f.string(),slug:f.string()}),FL=TQ.extend({entityType:f.literal("series"),metadata:A_w}),$f0=FL.extend({frontmatter:WG}),Q_w=$f0.extend({description:f.string().optional(),postCount:f.number(),coverImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()}),c22=f.object({description:f.string().optional()});function ZM(A){return new Y6(c22,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}fA();class sa0 extends r2{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:FL,frontmatterSchema:WG,supportsCoverImage:!0,bodyFormatter:ZM("")})}toMarkdown(A){let Q,w={};try{Q=this.parseFrontMatter(A.content,WG).coverImageId,w=ZM(A.metadata.title).parse(this.extractBody(A.content))}catch{}let $={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},X=ZM(A.metadata.title).format(w);return this.buildMarkdown(X,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,WG);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,WG);return ZM(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var IL=new sa0;fA();k2();Kf();C0();var w_w=f.object({seriesName:f.string().optional(),seriesIndex:f.number().optional()});function Bf0(A){let Q=w_w.safeParse(A);return Q.success?Q.data:{}}function fM(A){return Bf0(A.metadata).seriesName}function l22(A){return Bf0(A.metadata).seriesIndex}function p22(A,Q){let w=l22(A)??Number.MAX_SAFE_INTEGER,$=l22(Q)??Number.MAX_SAFE_INTEGER;return w-$}class aa0{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=q1(B);$.add(X);let Y=w.get(X),Z=Y?.content??this.createSeriesContent(B),H=b6(Z);if(Y?.contentHash===H)continue;let W={id:X,entityType:"series",content:Z,contentHash:H,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:B,slug:q1(B)}};await this.entityService.upsertEntity({entity:W}),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=fM(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=q1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let $=this.createSeriesContent(A),B={id:Q,entityType:"series",content:$,contentHash:b6($),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:q1(A)}};await this.entityService.upsertEntity({entity:B}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=q1(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=fM(B);if(X)A.add(X)}}return A}createSeriesContent(A){let Q={title:A,slug:q1(A)};return l5("",Q)}}fA();C0();var $_w=f.object({entityType:f.literal("series"),query:f.looseObject({id:f.string().optional(),limit:f.number().optional(),page:f.number().optional(),pageSize:f.number().optional()})}),B_w=f.object({type:f.enum(["list","detail"]),seriesName:f.string().optional()});function X_w(A){let Q=B_w.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let w=$_w.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 i22(A){let Q=BQ(A.content,WG);return $f0.parse({...A,frontmatter:Q.metadata})}class ta0{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 $=X_w(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=i22(X),Z=IL.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=i22($),X=IL.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=fM(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(p22),w}}fA();C0();Kf();var Y_w=f.object({prompt:f.string().optional(),title:f.string().optional(),seriesId:f.string().optional()}),Z_w=f.object({title:f.string().optional(),excerpt:f.string().optional()});class Xf0{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}
|
|
6974
|
+
`}},void 0,!1,void 0,this),q4("header",{className:"printable-hero",children:[q4("div",{className:"printable-masthead",children:Q.brandLabel&&q4("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this)},void 0,!1,void 0,this),q4("div",{children:[q4("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.excerpt&&q4("p",{className:"printable-excerpt",children:Q.excerpt},void 0,!1,void 0,this),q4("div",{className:"printable-meta",children:[Q.author&&q4("span",{children:["By ",Q.author]},void 0,!0,void 0,this),w&&q4("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&&q4("figure",{className:"printable-cover-wrap",children:q4("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this)},void 0,!1,void 0,this),q4(i9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.brandLabel))&&q4("footer",{className:"printable-footer",children:[q4("span",{children:Q.brandLabel??"Printable PDF"},void 0,!1,void 0,this),Q.canonicalUrl&&q4("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 ykw=26214400,gkw=60000;class da0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??HG}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==wf0)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=Ekw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await Rkw(Ckw(hkw(),"brain-blog-printable-"));try{let B=await zH({outputDir:$,mediaPath:`/_media/printable/post/${Q.id}`,template:y22,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await VH({rootDir:$});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:ykw,timeoutMs:gkw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${Tkw(Q)}-printable.pdf`}}finally{await X.close()}}finally{await vkw($,{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}=p6(A.content),w=y8.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 Ekw(A,Q={}){let{frontmatter:w,content:$}=p6(A.content),B=y8.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 Tkw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}import{mkdtemp as lkw,rm as pkw}from"fs/promises";import{tmpdir as ikw}from"os";import{join as dkw}from"path";K7();k2();DH();C0();import{jsxDEV as ckw}from"preact/jsx-dev-runtime";var Vs="og-image",Skw="blog:og-image",g22=f.object({title:f.string().min(1),excerpt:f.string().optional(),author:f.string().optional(),publishedAt:f.string().optional(),brandLabel:f.string().optional(),coverImageUrl:f.string().optional()}),E22={name:Skw,pluginId:"blog",schema:g22,renderers:{image:ukw}};function mkw(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 ukw(A){let Q=g22.parse(A);return ckw(EV,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Journal",title:Q.title,subtitle:Q.excerpt,meta:[Q.author],tag:mkw(Q.publishedAt)},void 0,!1,void 0,this)}var nkw={width:1200,height:630},rkw=60000;class na0{metadata={outputEntityType:"image",targetField:"ogImageId"};context;screenshotPng;constructor(A,Q={}){this.context=A,this.screenshotPng=Q.screenshotPng??zs}async resolve(A){if(A.sourceEntityType!=="post"||A.attachmentType!==Vs)return;let Q=await this.context.entityService.getEntity({entityType:"post",id:A.sourceEntityId});if(!Q)return;let w=okw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await lkw(dkw(ikw(),"brain-blog-og-image-"));try{let B=await zH({outputDir:$,mediaPath:`/_media/og/post/${Q.id}`,template:E22,format:"image",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await VH({rootDir:$});try{return{type:"image",data:await this.screenshotPng(X.urlFor(B.urlPath),nkw,{timeoutMs:rkw,fullPage:!1,omitBackground:!1}),mimeType:"image/png",filename:`${skw(Q)}-og.png`}}finally{await X.close()}}finally{await pkw($,{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}=p6(A.content),w=y8.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 okw(A,Q={}){let{frontmatter:w}=p6(A.content),$=y8.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 skw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}var T22={name:"@brains/blog",version:"0.2.0-alpha.169",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 ra0 extends fw{entityType=eV.entityType;schema=VE;adapter=eV;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("blog",T22,A,Ca0)}getEntityTypeConfig(){return{weight:2,publish:{publishStatuses:["queued","published"]}}}createGenerationHandler(A){return new ya0(this.logger.child("BlogGenerationJobHandler"),A)}getTemplates(){return I22()}getDataSources(){return[new Ea0(this.logger.child("BlogDataSource"))]}async onRegister(A){let{RSSDataSource:Q}=await Promise.resolve().then(() => (u22(),m22));A.entities.registerDataSource(new Q(this.logger.child("RSSDataSource"))),b22(A,this.logger),L22(A,this.logger),_22(A,this.logger),N22(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("post",wf0,new da0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("post",Vs,new na0(A)),this.deferPublishAssetRegistration(A),this.unregisterAtprotoProjection=NB.getInstance().register(ma0()),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:Vs,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 oa0(A={}){return new ra0(A)}DH();FE();fA();C0();H5();fA();C0();var WG=f.object({title:f.string(),slug:f.string(),coverImageId:f.string().optional()}),ekw=f.object({title:f.string(),slug:f.string()}),A_w=f.object({title:f.string(),slug:f.string()}),FL=TQ.extend({entityType:f.literal("series"),metadata:A_w}),$f0=FL.extend({frontmatter:WG}),Q_w=$f0.extend({description:f.string().optional(),postCount:f.number(),coverImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()}),c22=f.object({description:f.string().optional()});function ZM(A){return new Y6(c22,{title:A,mappings:[{key:"description",label:"Description",type:"string"}]})}fA();class sa0 extends r2{constructor(){super({entityType:"series",purpose:"A series grouping related posts or content under one theme.",schema:FL,frontmatterSchema:WG,supportsCoverImage:!0,bodyFormatter:ZM("")})}toMarkdown(A){let Q,w={};try{Q=this.parseFrontMatter(A.content,WG).coverImageId,w=ZM(A.metadata.title).parse(this.extractBody(A.content))}catch{}let $={title:A.metadata.title,slug:A.metadata.slug,...Q&&{coverImageId:Q}},X=ZM(A.metadata.title).format(w);return this.buildMarkdown(X,$)}fromMarkdown(A){let Q=this.parseFrontMatter(A,WG);return{content:A,entityType:"series",metadata:{title:Q.title,slug:Q.slug}}}parseBody(A){try{let Q=this.parseFrontMatter(A,WG);return ZM(Q.title).parse(this.extractBody(A))}catch{return{}}}generateFrontMatter(){return""}}var IL=new sa0;fA();k2();Kf();C0();var w_w=f.object({seriesName:f.string().optional(),seriesIndex:f.number().optional()});function Bf0(A){let Q=w_w.safeParse(A);return Q.success?Q.data:{}}function fM(A){return Bf0(A.metadata).seriesName}function l22(A){return Bf0(A.metadata).seriesIndex}function p22(A,Q){let w=l22(A)??Number.MAX_SAFE_INTEGER,$=l22(Q)??Number.MAX_SAFE_INTEGER;return w-$}class aa0{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=q1(B);$.add(X);let Y=w.get(X),Z=Y?.content??this.createSeriesContent(B),H=b6(Z);if(Y?.contentHash===H)continue;let W={id:X,entityType:"series",content:Z,contentHash:H,created:Y?.created??new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:B,slug:q1(B)}};await this.entityService.upsertEntity({entity:W}),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=fM(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=q1(A);if(await this.entityService.getEntity({entityType:"series",id:Q}))return;let $=this.createSeriesContent(A),B={id:Q,entityType:"series",content:$,contentHash:b6($),created:new Date().toISOString(),updated:new Date().toISOString(),visibility:"public",metadata:{title:A,slug:q1(A)}};await this.entityService.upsertEntity({entity:B}),this.logger.debug(`Created series: ${A}`)}async cleanupOrphanedSeries(A){let Q=q1(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=fM(B);if(X)A.add(X)}}return A}createSeriesContent(A){let Q={title:A,slug:q1(A)};return l5("",Q)}}fA();C0();var $_w=f.object({entityType:f.literal("series"),query:f.looseObject({id:f.string().optional(),limit:f.number().optional(),page:f.number().optional(),pageSize:f.number().optional()})}),B_w=f.object({type:f.enum(["list","detail"]),seriesName:f.string().optional()});function X_w(A){let Q=B_w.safeParse(A);if(Q.success)return{type:Q.data.type,seriesName:Q.data.seriesName};let w=$_w.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 i22(A){let Q=BQ(A.content,WG);return $f0.parse({...A,frontmatter:Q.metadata})}class ta0{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 $=X_w(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=i22(X),Z=IL.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=i22($),X=IL.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=fM(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(p22),w}}fA();C0();Kf();var Y_w=f.object({prompt:f.string().optional(),title:f.string().optional(),seriesId:f.string().optional()}),Z_w=f.object({title:f.string().optional(),excerpt:f.string().optional()});class Xf0{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}
|
|
6975
6975
|
|
|
6976
6976
|
Content in this series:
|
|
6977
6977
|
${$.join(`
|
|
@@ -6983,7 +6983,7 @@ Your task is to write a series description (2-3 sentences) that:
|
|
|
6983
6983
|
3. Is engaging and makes readers want to explore the content
|
|
6984
6984
|
4. Works well as a series overview on a website
|
|
6985
6985
|
|
|
6986
|
-
Be concise and focus on what makes this series unique and valuable.`});async function e22({entity:A,config:Q}){let w=FL.parse(A),$=IL.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 ea0(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:m6["ai.rizom.brain.series"],validate:!1,buildRecord:e22}}var AQ2={name:"@brains/series",version:"0.2.0-alpha.
|
|
6986
|
+
Be concise and focus on what makes this series unique and valuable.`});async function e22({entity:A,config:Q}){let w=FL.parse(A),$=IL.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 ea0(){return{entityType:"series",collection:"ai.rizom.brain.series",lexicon:m6["ai.rizom.brain.series"],validate:!1,buildRecord:e22}}var AQ2={name:"@brains/series",version:"0.2.0-alpha.169",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 QQ2=f.discriminatedUnion("mode",[f.object({mode:f.literal("derive"),reason:f.string().optional()}),f.object({mode:f.literal("source"),entityId:f.string(),entityType:f.string(),seriesName:f.string().optional(),previousSeriesName:f.string().optional()})]);class At0 extends fw{entityType="series";schema=FL;adapter=IL;manager;unregisterAtprotoProjection;constructor(){super("series",AQ2,{},o7)}getEntityTypeConfig(){return{weight:0.5}}createGenerationHandler(A){return new Xf0(this.logger.child("SeriesGenerationHandler"),A)}getTemplates(){return{...a22(),description:t22}}getDataSources(){return[new ta0(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=fM(Q.entity),$=Bf0(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 aa0(A.entityService,this.logger.child("SeriesManager")),this.unregisterAtprotoProjection=NB.getInstance().register(ea0())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}createSeriesProjectionHandler(A){return{process:async(Q)=>{let w=QQ2.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=QQ2.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 Xf0(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 Qt0(){return new At0}fA();C0();fA();k2();C0();fA();var wQ2=f.enum(["generating","draft","queued","published","failed"]),$Q2=f.enum(["generating","draft","queued","published","failed"]),wt0="publishedAt is required when deck status is published",$t0=(A)=>A.status==="published"&&!A.publishedAt,Bt0=(A)=>{if($t0(A))throw Error(wt0)},Cq=f.object({title:f.string(),slug:f.string().optional(),description:f.string().optional(),author:f.string().optional(),status:wQ2,publishedAt:f.string().datetime().optional(),event:f.string().optional(),coverImageId:f.string().optional(),ogImageId:f.string().optional()}),Rz8=f.object({title:f.string(),description:f.string().optional(),status:wQ2,publishedAt:f.string().datetime().optional(),coverImageId:f.string().optional(),slug:f.string(),error:f.string().optional()}).superRefine((A,Q)=>{if(!$t0(A))return;Q.addIssue({code:f.ZodIssueCode.custom,path:["publishedAt"],message:wt0})}),z_w=f.object({title:f.string(),description:f.string().optional(),status:$Q2,publishedAt:f.string().datetime().optional(),coverImageId:f.string().optional(),slug:f.string(),error:f.string().optional()}).superRefine((A,Q)=>{if(!$t0(A))return;Q.addIssue({code:"custom",path:["publishedAt"],message:wt0})}),V_w=f.object({title:f.string(),slug:f.string().optional(),description:f.string().optional(),author:f.string().optional(),status:$Q2,publishedAt:f.string().datetime().optional(),event:f.string().optional(),coverImageId:f.string().optional(),ogImageId:f.string().optional()}),bE=TQ.extend({entityType:f.literal("deck"),metadata:z_w}),Yf0=bE.extend({frontmatter:V_w,body:f.string(),ogImageUrl:f.string().optional()}),Js=Yf0.extend({url:f.string().optional(),typeLabel:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),coverImageUrl:f.string().optional(),ogImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()});class Xt0 extends r2{constructor(){super({entityType:"deck",purpose:"A slide-deck presentation.",schema:bE,frontmatterSchema:Cq,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,Cq);Bt0(w);let $={...w,slug:w.slug??A.metadata.slug};return this.buildMarkdown(Q,$)}fromMarkdown(A){let Q=this.parseFrontmatter(A),w=this.extractBody(A);Bt0(Q),this.validateSlideStructure(w);let $=Q.slug??q1(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(`---
|
|
6987
6987
|
`,Q),metadata:{title:A.title,slug:A.id,status:"generating"}}}}var Fs=new Xt0;C0();n$();var J_w=f.object({markdown:f.string().describe("Markdown content with slide separators (---)"),deck:Js.optional()}),Yt0=s1({name:"deck-detail",description:"Render a presentation deck as Reveal.js slides",schema:J_w,dataSourceId:"decks:entities",requiredPermission:"public",layout:{component:Lr0,fullscreen:!0}});n$();C0();var Zt0=f.object({decks:f.array(Yf0)}),ft0=f.object({decks:f.array(Js),pageTitle:f.string().optional(),pageLabel:f.string().optional()});import{jsxDEV as Ht0}from"preact/jsx-dev-runtime";var F_w="Presentations",Wt0=({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 Ht0("div",{className:"deck-list bg-theme",children:Ht0("div",{className:"container mx-auto max-w-[1100px] px-6 py-16 md:px-12 md:py-24",children:Ht0(fo,{label:Q&&Q!=="Decks"?Q:F_w,items:w},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)};H5();class Zf0 extends Y6{constructor(){super(Zt0,{title:"Deck List",mappings:[{key:"decks",label:"Decks",type:"array",itemType:"object"}]})}}var Kt0=s1({name:"deck-list",description:"List view of all presentation decks",schema:ft0,dataSourceId:"decks:entities",requiredPermission:"public",formatter:new Zf0,layout:{component:Wt0}});C0();fA();var I_w=f.object({title:f.string().max(80).describe("A short, punchy title (2-5 words) that's memorable and evocative"),content:f.string().describe("Full slide deck content in markdown format with slide separators (---). Each slide should have a header and focused content."),description:f.string().describe("A concise 1-2 sentence summary that captures the essence of the talk")}),BQ2=s1({name:"decks:generation",description:"Template for AI to generate complete slide decks from prompts",schema:I_w,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are creating slide decks in a distinctive voice that blends philosophy, technology, and culture.
|
|
6988
6988
|
|
|
6989
6989
|
Your task is to generate a complete slide deck based on the user's prompt.
|
|
@@ -7291,7 +7291,7 @@ ${Z}`,templateName:"decks:description"})).description,await this.reportProgress(
|
|
|
7291
7291
|
color: var(--carousel-accent);
|
|
7292
7292
|
font-weight: 600;
|
|
7293
7293
|
}
|
|
7294
|
-
`}},void 0,!1,void 0,this),B.map((W,K)=>VX("section",{className:`deck-carousel-slide${K===0?" is-cover":""}`,children:[VX("header",{className:"deck-carousel-header",children:VX("span",{className:"deck-carousel-wordmark","aria-label":w??Q,children:[VX("span",{className:"wm-primary",children:X.primary},void 0,!1,void 0,this),X.secondary!==void 0&&VX(j_w,{children:[VX("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),VX("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),VX("div",{className:"deck-carousel-body",children:VX("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:H(W.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),VX("footer",{className:"deck-carousel-footer",children:[VX("span",{className:"deck-carousel-footer-meta",children:$??Q},void 0,!1,void 0,this),VX("span",{className:"deck-carousel-counter","aria-label":`Slide ${K+1} of ${Y}`,children:[VX("span",{className:"deck-carousel-counter-current",children:String(K+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",VX("span",{children:Z},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},K,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as P_w,rm as M_w}from"fs/promises";import{tmpdir as O_w}from"os";import{join as x_w}from"path";K7();k2();var R_w=26214400,v_w=60000,HQ2=20;class Dt0{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??HG,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=h_w(Q,{brandLabel:this.resolveBrandLabel()});if(w.slides.length>HQ2)throw Error(`Refusing to render carousel with ${w.slides.length} slides; maxSlides=${HQ2}`);let $=await this.getThemeMode(),B=await P_w(x_w(O_w(),"brain-deck-carousel-"));try{let X=await zH({outputDir:B,mediaPath:`/_media/carousel/${Q.id}`,template:fQ2,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:$},themeCSS:this.context.themeCSS}),Y=await VH({rootDir:B});try{return{type:"document",data:await this.renderPdf(Y.urlFor(X.urlPath),{maxBytes:R_w,timeoutMs:v_w,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${C_w(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await M_w(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 h_w(A,Q={}){let{frontmatter:w,content:$}=p6(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 C_w(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}C0();import{jsxDEV as E_w}from"preact/jsx-dev-runtime";var ff0="og-image",y_w="decks:og-image",WQ2=f.object({title:f.string().min(1),description:f.string().optional(),event:f.string().optional(),brandLabel:f.string().optional(),slideCount:f.number().int().positive().optional(),coverImageUrl:f.string().optional()}),KQ2={name:y_w,pluginId:"decks",schema:WQ2,renderers:{image:g_w}};function g_w(A){let Q=WQ2.parse(A),w=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return E_w(EV,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:w},void 0,!1,void 0,this)}K7();k2();class qt0{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!==ff0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:$}=p6(Q.content),B=Cq.parse(w),X=T_w($),Y=this.resolveBrandLabel(),Z=await this.resolveCoverImageUrl(B.coverImageId),H={title:B.title,...B.description?{description:B.description}:{},...B.event?{event:B.event}:{},...X?{slideCount:X}:{},...Z?{coverImageUrl:Z}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await YM({mediaPath:`/_media/og/deck/${Q.id}`,template:KQ2,content:H,title:H.title,themeMode:"dark",themeCSS:this.context.themeCSS,tmpPrefix:"brain-deck-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${S_w(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 T_w(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function S_w(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}fA();async function UQ2({entity:A,config:Q}){let w=bE.parse(A),$=BQ(w.content,Cq),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 zt0(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:m6["ai.rizom.brain.deck"],validate:!1,buildRecord:UQ2}}var GQ2={name:"@brains/decks",version:"0.2.0-alpha.
|
|
7294
|
+
`}},void 0,!1,void 0,this),B.map((W,K)=>VX("section",{className:`deck-carousel-slide${K===0?" is-cover":""}`,children:[VX("header",{className:"deck-carousel-header",children:VX("span",{className:"deck-carousel-wordmark","aria-label":w??Q,children:[VX("span",{className:"wm-primary",children:X.primary},void 0,!1,void 0,this),X.secondary!==void 0&&VX(j_w,{children:[VX("span",{className:"wm-dot",children:"."},void 0,!1,void 0,this),VX("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),VX("div",{className:"deck-carousel-body",children:VX("div",{className:"deck-carousel-content",dangerouslySetInnerHTML:{__html:H(W.markdown)}},void 0,!1,void 0,this)},void 0,!1,void 0,this),VX("footer",{className:"deck-carousel-footer",children:[VX("span",{className:"deck-carousel-footer-meta",children:$??Q},void 0,!1,void 0,this),VX("span",{className:"deck-carousel-counter","aria-label":`Slide ${K+1} of ${Y}`,children:[VX("span",{className:"deck-carousel-counter-current",children:String(K+1).padStart(2,"0")},void 0,!1,void 0,this)," / ",VX("span",{children:Z},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},K,!0,void 0,this))]},void 0,!0,void 0,this)}import{mkdtemp as P_w,rm as M_w}from"fs/promises";import{tmpdir as O_w}from"os";import{join as x_w}from"path";K7();k2();var R_w=26214400,v_w=60000,HQ2=20;class Dt0{metadata={outputEntityType:"document"};context;renderPdf;getThemeMode;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??HG,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=h_w(Q,{brandLabel:this.resolveBrandLabel()});if(w.slides.length>HQ2)throw Error(`Refusing to render carousel with ${w.slides.length} slides; maxSlides=${HQ2}`);let $=await this.getThemeMode(),B=await P_w(x_w(O_w(),"brain-deck-carousel-"));try{let X=await zH({outputDir:B,mediaPath:`/_media/carousel/${Q.id}`,template:fQ2,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:$},themeCSS:this.context.themeCSS}),Y=await VH({rootDir:B});try{return{type:"document",data:await this.renderPdf(Y.urlFor(X.urlPath),{maxBytes:R_w,timeoutMs:v_w,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${C_w(Q)}-carousel.pdf`}}finally{await Y.close()}}finally{await M_w(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 h_w(A,Q={}){let{frontmatter:w,content:$}=p6(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 C_w(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}C0();import{jsxDEV as E_w}from"preact/jsx-dev-runtime";var ff0="og-image",y_w="decks:og-image",WQ2=f.object({title:f.string().min(1),description:f.string().optional(),event:f.string().optional(),brandLabel:f.string().optional(),slideCount:f.number().int().positive().optional(),coverImageUrl:f.string().optional()}),KQ2={name:y_w,pluginId:"decks",schema:WQ2,renderers:{image:g_w}};function g_w(A){let Q=WQ2.parse(A),w=Q.slideCount?`${Q.slideCount} slide${Q.slideCount===1?"":"s"}`:void 0;return E_w(EV,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Deck",title:Q.title,subtitle:Q.description,meta:[Q.event],tag:w},void 0,!1,void 0,this)}K7();k2();class qt0{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!==ff0)return;let Q=await this.context.entityService.getEntity({entityType:"deck",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:$}=p6(Q.content),B=Cq.parse(w),X=T_w($),Y=this.resolveBrandLabel(),Z=await this.resolveCoverImageUrl(B.coverImageId),H={title:B.title,...B.description?{description:B.description}:{},...B.event?{event:B.event}:{},...X?{slideCount:X}:{},...Z?{coverImageUrl:Z}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await YM({mediaPath:`/_media/og/deck/${Q.id}`,template:KQ2,content:H,title:H.title,themeMode:"dark",themeCSS:this.context.themeCSS,tmpPrefix:"brain-deck-og-image-",...this.deps.screenshotPng&&{screenshotPng:this.deps.screenshotPng}}),mimeType:"image/png",filename:`${S_w(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 T_w(A){return A.split(/^---$/gm).map((Q)=>Q.trim()).filter((Q)=>Q.length>0).length}function S_w(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}fA();async function UQ2({entity:A,config:Q}){let w=bE.parse(A),$=BQ(w.content,Cq),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 zt0(){return{entityType:"deck",collection:"ai.rizom.brain.deck",lexicon:m6["ai.rizom.brain.deck"],validate:!1,buildRecord:UQ2}}var GQ2={name:"@brains/decks",version:"0.2.0-alpha.169",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 u_w=f.object({prompt:f.string(),event:f.string().optional()}),c_w=f.object({title:f.string(),content:f.string()});class Vt0 extends fw{deps;entityType=Fs.entityType;schema=Fs.schema;adapter=Fs;unregisterCarouselAttachmentProvider;unregisterOgImageAttachmentProvider;unregisterAtprotoProjection;constructor(A={}){super("decks",GQ2,{},o7);this.deps=A}createGenerationHandler(A){return new Gt0(this.logger.child("DeckGenerationJobHandler"),A)}getTemplates(){return{"deck-detail":Yt0,"deck-list":Kt0,generation:BQ2,description:XQ2}}getDataSources(){return[new Ut0(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=NB.getInstance().register(zt0()),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:dA(B)}})}return{success:!0}})}registerCarouselAttachmentProvider(A){let Q={...this.deps,getThemeMode:this.deps.getThemeMode??(async()=>{try{return(await Ks(A.entityService)).themeMode??"dark"}catch{return"dark"}})};this.unregisterCarouselAttachmentProvider=A.attachments.register("deck",YQ2,new Dt0(A,Q))}registerOgImageAttachmentProvider(A){this.unregisterOgImageAttachmentProvider=A.attachments.register("deck",ff0,new qt0(A))}registerEvalHandlers(A){A.eval.registerHandler("generateDeck",async(Q)=>{let w=u_w.parse(Q);return A.ai.generate({prompt:`${w.prompt}${w.event?`
|
|
7295
7295
|
|
|
7296
7296
|
Note: This presentation is for "${w.event}".`:""}`,templateName:"decks:generation"})}),A.eval.registerHandler("generateDescription",async(Q)=>{let w=c_w.parse(Q);return A.ai.generate({prompt:`Title: ${w.title}
|
|
7297
7297
|
|
|
@@ -7448,9 +7448,9 @@ ${w.content}`,templateName:"decks:description"})})}}function bs(){return new Vt0
|
|
|
7448
7448
|
background: transparent;
|
|
7449
7449
|
}
|
|
7450
7450
|
|
|
7451
|
-
`,kQ2=()=>G9("style",{children:r_w},void 0,!1,void 0,this);import{jsxDEV as i2,Fragment as o_w}from"preact/jsx-dev-runtime";var Gf0=({title:A,description:Q,children:w,detail:$=!1,footer:B=!1,contentClassName:X=""})=>i2(o_w,{children:[i2(Bw,{title:A,description:Q},void 0,!1,void 0,this),i2(kQ2,{},void 0,!1,void 0,this),i2("div",{className:`docs-handbook${$?" docs-handbook--detail":""}`,children:[i2(bQ2,{},void 0,!1,void 0,this),i2("div",{className:`${yq.wrap} ${X}`.trim(),children:[w,B&&i2(LQ2,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),_Q2=({docsCount:A,sectionsCount:Q,startDoc:w})=>i2("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[i2("p",{className:`${yq.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),i2("h1",{className:`${yq.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",i2("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i2("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),i2("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:[i2("div",{children:[i2("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),i2("div",{children:[i2("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),i2("div",{children:[i2("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),i2("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[w&&i2("a",{className:yq.primaryButton,href:kE(w),children:"Start reading"},void 0,!1,void 0,this),i2("a",{className:yq.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),NQ2=({groups:A})=>i2("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:[i2("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),i2("ol",{className:"m-0 list-none p-0",children:A.map((Q,w)=>i2("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[i2("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[_E(w),"."]},void 0,!0,void 0,this),i2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${Uf0(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),jQ2=({group:A,index:Q})=>i2("article",{className:"mb-16 last:mb-0",id:Uf0(Q),children:[i2("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:[i2("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[_E(Q),"."]},void 0,!0,void 0,this),i2("h2",{className:`${yq.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),i2("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i2("ol",{className:"m-0 list-none p-0",children:A.docs.map((w)=>i2("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:i2("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:kE(w),children:[i2("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&&i2("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),PQ2=({title:A})=>i2("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:[i2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),i2("span",{children:"/"},void 0,!1,void 0,this),i2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),i2("span",{children:"/"},void 0,!1,void 0,this),i2("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),MQ2=({groups:A,activeGroupIndex:Q,activeSlug:w})=>i2("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:i2("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[i2("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),i2("ol",{className:"m-0 list-none p-0",children:A.map(($,B)=>{let X=B===Q;return i2("li",{className:X?"mb-[22px]":"mb-3.5",children:[i2("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#${Uf0(B)}`,children:[i2("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[_E(B),"."]},void 0,!0,void 0,this)," ",$.section]},void 0,!0,void 0,this),X&&i2("ol",{className:"mt-0.5 list-none p-0",children:$.docs.map((Y)=>{let Z=Y.metadata.slug===w;return i2("li",{children:i2("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:kE(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),OQ2=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return i2("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?i2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:kE(A),children:[i2("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),i2("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):i2("span",{},void 0,!1,void 0,this),Q&&i2("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:kE(Q),children:[i2("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),i2("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 NE}from"preact/jsx-dev-runtime";var bt0=({docs:A})=>{let Q=Ls(A),w=Kf0(Q),B=Q.filter((X)=>X.metadata.slug!=="index")[0]??Q[0];return NE(Gf0,{title:"Documentation",description:"Brains documentation",children:[NE(_Q2,{docsCount:A.length,sectionsCount:w.length,startDoc:B},void 0,!1,void 0,this),NE("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:[NE(NQ2,{groups:w},void 0,!1,void 0,this),NE("div",{children:w.map((X,Y)=>NE(jQ2,{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 JH}from"preact/jsx-dev-runtime";var Lt0=({doc:A,docs:Q,prevDoc:w,nextDoc:$})=>{let B=Kf0(Q.length>0?Q:[A]),X=Ls(Q.length>0?Q:[A]),Y=X.findIndex((H)=>H.metadata.slug===A.metadata.slug),Z=Math.max(B.findIndex((H)=>H.docs.some((W)=>W.metadata.slug===A.metadata.slug)),0);return JH(Gf0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[JH(PQ2,{title:A.metadata.title},void 0,!1,void 0,this),JH("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[JH(MQ2,{groups:B,activeGroupIndex:Z,activeSlug:A.metadata.slug},void 0,!1,void 0,this),JH("article",{className:"min-w-0",children:[JH("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[JH("p",{className:`${yq.label} m-0 mb-6 flex items-baseline gap-3`,children:[JH("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[_E(Z),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${X.length}`:""]},void 0,!0,void 0,this),JH("h1",{className:`${yq.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&&JH("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),JH("div",{className:"docs-article__body",children:JH(i9,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),JH(OQ2,{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 s_w=f.object({currentPage:f.number(),totalPages:f.number(),totalItems:f.number(),pageSize:f.number(),hasNextPage:f.boolean(),hasPrevPage:f.boolean()}),a_w=f.union([f.enum(["public","shared","restricted"]),f.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),t_w=f.object({title:f.string(),section:f.string(),order:f.number().int(),sourcePath:f.string(),description:f.string().optional(),slug:f.string().optional()}),e_w=f.object({title:f.string(),section:f.string(),order:f.number().int(),description:f.string().optional(),slug:f.string()}),ks=f.object({id:f.string(),entityType:f.literal("doc"),content:f.string(),created:f.string(),updated:f.string(),visibility:a_w,metadata:e_w,contentHash:f.string(),frontmatter:t_w,body:f.string()}),ANw=f.object({docs:f.array(ks),pagination:s_w.nullable(),baseUrl:f.string().optional()}),QNw=f.object({doc:ks,docs:f.array(ks),prevDoc:ks.nullable(),nextDoc:ks.nullable()});function xQ2(){return{"doc-list":s1({name:"doc-list",description:"Documentation index template",schema:ANw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:bt0}}),"doc-detail":s1({name:"doc-detail",description:"Documentation page template",schema:QNw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:Lt0}})}}var RQ2={name:"@brains/doc",version:"0.2.0-alpha.168",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 kt0 extends fw{entityType=Hf0.entityType;schema=LE;adapter=Hf0;constructor(){super("docs",RQ2,{},o7)}getTemplates(){return xQ2()}getDataSources(){return[new Wf0(this.logger.child("DocDataSource"))]}}function _s(){return new kt0}fA();k2();C0();B8();C0();var _t0=f.literal("application/pdf"),vQ2=f.enum(["pending","draft","failed"]),Nt0=f.object({title:f.string().optional(),mimeType:_t0,filename:f.string().min(1),pageCount:f.number().int().min(0).optional(),status:vQ2.optional(),processingJobId:f.string().optional(),processingError:f.string().optional(),sourceEntityType:f.string().min(1).optional(),sourceEntityId:f.string().min(1).optional(),sourceUploadId:f.string().optional(),sourceFilename:f.string().optional(),sourceMediaType:f.string().optional(),attachmentType:f.string().min(1).optional(),dedupKey:f.string().min(1).optional()}),jE=TQ.extend({entityType:f.literal("document"),content:f.string().regex(/^data:application\/pdf;base64,.+$/),metadata:Nt0});function Ns(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 Df0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function jt0(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 qf0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=jE;toMarkdown(A){return A.content}fromMarkdown(A){return Ns(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:$}=Ns(Q);return{entityType:"document",content:Q,metadata:{mimeType:$,...w}}}}var AJ=new qf0;async function Ue0(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(() => (u62(),m62))).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 W=1;W<=X.numPages;W+=1){let G=(await(await X.getPage(W)).getTextContent()).items.flatMap((q)=>("str"in q)?[q.str]:[]).join(" ").replace(/\s+/g," ").trim();if(G.length>0)Z.push(G)}let H=Z.join(`
|
|
7451
|
+
`,kQ2=()=>G9("style",{children:r_w},void 0,!1,void 0,this);import{jsxDEV as i2,Fragment as o_w}from"preact/jsx-dev-runtime";var Gf0=({title:A,description:Q,children:w,detail:$=!1,footer:B=!1,contentClassName:X=""})=>i2(o_w,{children:[i2(Bw,{title:A,description:Q},void 0,!1,void 0,this),i2(kQ2,{},void 0,!1,void 0,this),i2("div",{className:`docs-handbook${$?" docs-handbook--detail":""}`,children:[i2(bQ2,{},void 0,!1,void 0,this),i2("div",{className:`${yq.wrap} ${X}`.trim(),children:[w,B&&i2(LQ2,{},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),_Q2=({docsCount:A,sectionsCount:Q,startDoc:w})=>i2("section",{className:"border-b border-[var(--docs-text)] py-14 md:py-24 md:pb-[72px]",children:[i2("p",{className:`${yq.label} mb-8`,children:"Handbook \xB7 Brains docs"},void 0,!1,void 0,this),i2("h1",{className:`${yq.display} m-0 max-w-[16ch] text-5xl leading-[1.05] tracking-[-0.02em] md:text-7xl`,children:["Build, run, and publish"," ",i2("em",{className:"text-[var(--docs-accent)]",children:"brains."},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i2("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),i2("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:[i2("div",{children:[i2("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),i2("div",{children:[i2("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),i2("div",{children:[i2("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),i2("div",{className:"mt-9 flex flex-wrap gap-3.5",children:[w&&i2("a",{className:yq.primaryButton,href:kE(w),children:"Start reading"},void 0,!1,void 0,this),i2("a",{className:yq.button,href:"#sections",children:"Browse sections"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),NQ2=({groups:A})=>i2("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:[i2("p",{className:"m-0 mb-3.5 font-medium text-[var(--docs-text)]",children:"Sections"},void 0,!1,void 0,this),i2("ol",{className:"m-0 list-none p-0",children:A.map((Q,w)=>i2("li",{className:"grid grid-cols-[32px_1fr] gap-2 py-1.5",children:[i2("span",{className:"docs-font-display text-[var(--docs-text-light)] italic",children:[_E(w),"."]},void 0,!0,void 0,this),i2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:`#${Uf0(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),jQ2=({group:A,index:Q})=>i2("article",{className:"mb-16 last:mb-0",id:Uf0(Q),children:[i2("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:[i2("span",{className:"text-right docs-font-display text-3xl leading-[1.1] text-[var(--docs-accent)] italic md:text-4xl",children:[_E(Q),"."]},void 0,!0,void 0,this),i2("h2",{className:`${yq.display} m-0 text-3xl leading-[1.1] tracking-[-0.015em] md:text-4xl`,children:A.section},void 0,!1,void 0,this),i2("span",{className:"docs-chapter__leader"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),i2("ol",{className:"m-0 list-none p-0",children:A.docs.map((w)=>i2("li",{className:"border-b border-[var(--docs-border-light)] last:border-b-0",children:i2("a",{className:"group block py-[18px] pl-12 md:pl-[68px]",href:kE(w),children:[i2("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&&i2("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),PQ2=({title:A})=>i2("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:[i2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/",children:"Home"},void 0,!1,void 0,this),i2("span",{children:"/"},void 0,!1,void 0,this),i2("a",{className:"text-[var(--docs-text-muted)] hover:text-[var(--docs-accent)]",href:"/docs",children:"Docs"},void 0,!1,void 0,this),i2("span",{children:"/"},void 0,!1,void 0,this),i2("span",{children:A},void 0,!1,void 0,this)]},void 0,!0,void 0,this),MQ2=({groups:A,activeGroupIndex:Q,activeSlug:w})=>i2("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:i2("nav",{className:"docs-font-label text-xs tracking-[0.06em] text-[var(--docs-text-light)]",children:[i2("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),i2("ol",{className:"m-0 list-none p-0",children:A.map(($,B)=>{let X=B===Q;return i2("li",{className:X?"mb-[22px]":"mb-3.5",children:[i2("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#${Uf0(B)}`,children:[i2("span",{className:"docs-font-display text-sm text-[var(--docs-accent)] italic",children:[_E(B),"."]},void 0,!0,void 0,this)," ",$.section]},void 0,!0,void 0,this),X&&i2("ol",{className:"mt-0.5 list-none p-0",children:$.docs.map((Y)=>{let Z=Y.metadata.slug===w;return i2("li",{children:i2("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:kE(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),OQ2=({prevDoc:A,nextDoc:Q})=>{if(!A&&!Q)return null;return i2("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?i2("a",{className:"group border-t border-[var(--docs-border-light)] pt-[18px] transition-colors duration-150 hover:border-[var(--docs-accent)]",href:kE(A),children:[i2("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),i2("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):i2("span",{},void 0,!1,void 0,this),Q&&i2("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:kE(Q),children:[i2("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),i2("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 NE}from"preact/jsx-dev-runtime";var bt0=({docs:A})=>{let Q=Ls(A),w=Kf0(Q),B=Q.filter((X)=>X.metadata.slug!=="index")[0]??Q[0];return NE(Gf0,{title:"Documentation",description:"Brains documentation",children:[NE(_Q2,{docsCount:A.length,sectionsCount:w.length,startDoc:B},void 0,!1,void 0,this),NE("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:[NE(NQ2,{groups:w},void 0,!1,void 0,this),NE("div",{children:w.map((X,Y)=>NE(jQ2,{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 JH}from"preact/jsx-dev-runtime";var Lt0=({doc:A,docs:Q,prevDoc:w,nextDoc:$})=>{let B=Kf0(Q.length>0?Q:[A]),X=Ls(Q.length>0?Q:[A]),Y=X.findIndex((H)=>H.metadata.slug===A.metadata.slug),Z=Math.max(B.findIndex((H)=>H.docs.some((W)=>W.metadata.slug===A.metadata.slug)),0);return JH(Gf0,{title:A.metadata.title,description:A.metadata.description??A.metadata.section,detail:!0,footer:!0,contentClassName:"pt-16",children:[JH(PQ2,{title:A.metadata.title},void 0,!1,void 0,this),JH("div",{className:"grid items-start gap-10 py-8 pb-24 md:grid-cols-[240px_minmax(0,1fr)] md:gap-20",children:[JH(MQ2,{groups:B,activeGroupIndex:Z,activeSlug:A.metadata.slug},void 0,!1,void 0,this),JH("article",{className:"min-w-0",children:[JH("header",{className:"mb-10 border-b border-[var(--docs-border)] pb-8",children:[JH("p",{className:`${yq.label} m-0 mb-6 flex items-baseline gap-3`,children:[JH("span",{className:"docs-font-display text-lg leading-none tracking-normal normal-case text-[var(--docs-accent)] italic",children:[_E(Z),"."]},void 0,!0,void 0,this)," ",A.metadata.section,Y>=0?` \xB7 ${Y+1}/${X.length}`:""]},void 0,!0,void 0,this),JH("h1",{className:`${yq.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&&JH("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),JH("div",{className:"docs-article__body",children:JH(i9,{markdown:A.body},void 0,!1,void 0,this)},void 0,!1,void 0,this),JH(OQ2,{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 s_w=f.object({currentPage:f.number(),totalPages:f.number(),totalItems:f.number(),pageSize:f.number(),hasNextPage:f.boolean(),hasPrevPage:f.boolean()}),a_w=f.union([f.enum(["public","shared","restricted"]),f.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),t_w=f.object({title:f.string(),section:f.string(),order:f.number().int(),sourcePath:f.string(),description:f.string().optional(),slug:f.string().optional()}),e_w=f.object({title:f.string(),section:f.string(),order:f.number().int(),description:f.string().optional(),slug:f.string()}),ks=f.object({id:f.string(),entityType:f.literal("doc"),content:f.string(),created:f.string(),updated:f.string(),visibility:a_w,metadata:e_w,contentHash:f.string(),frontmatter:t_w,body:f.string()}),ANw=f.object({docs:f.array(ks),pagination:s_w.nullable(),baseUrl:f.string().optional()}),QNw=f.object({doc:ks,docs:f.array(ks),prevDoc:ks.nullable(),nextDoc:ks.nullable()});function xQ2(){return{"doc-list":s1({name:"doc-list",description:"Documentation index template",schema:ANw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:bt0}}),"doc-detail":s1({name:"doc-detail",description:"Documentation page template",schema:QNw,dataSourceId:"docs:entities",requiredPermission:"public",layout:{component:Lt0}})}}var RQ2={name:"@brains/doc",version:"0.2.0-alpha.169",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 kt0 extends fw{entityType=Hf0.entityType;schema=LE;adapter=Hf0;constructor(){super("docs",RQ2,{},o7)}getTemplates(){return xQ2()}getDataSources(){return[new Wf0(this.logger.child("DocDataSource"))]}}function _s(){return new kt0}fA();k2();C0();B8();C0();var _t0=f.literal("application/pdf"),vQ2=f.enum(["pending","draft","failed"]),Nt0=f.object({title:f.string().optional(),mimeType:_t0,filename:f.string().min(1),pageCount:f.number().int().min(0).optional(),status:vQ2.optional(),processingJobId:f.string().optional(),processingError:f.string().optional(),sourceEntityType:f.string().min(1).optional(),sourceEntityId:f.string().min(1).optional(),sourceUploadId:f.string().optional(),sourceFilename:f.string().optional(),sourceMediaType:f.string().optional(),attachmentType:f.string().min(1).optional(),dedupKey:f.string().min(1).optional()}),jE=TQ.extend({entityType:f.literal("document"),content:f.string().regex(/^data:application\/pdf;base64,.+$/),metadata:Nt0});function Ns(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 Df0(A){return`data:application/pdf;base64,${Buffer.from(A).toString("base64")}`}function jt0(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 qf0{entityType="document";purpose="A durable rendered file artifact such as a printable or carousel PDF.";schema=jE;toMarkdown(A){return A.content}fromMarkdown(A){return Ns(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:$}=Ns(Q);return{entityType:"document",content:Q,metadata:{mimeType:$,...w}}}}var AJ=new qf0;async function Ue0(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(() => (u62(),m62))).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 W=1;W<=X.numPages;W+=1){let G=(await(await X.getPage(W)).getTextContent()).items.flatMap((q)=>("str"in q)?[q.str]:[]).join(" ").replace(/\s+/g," ").trim();if(G.length>0)Z.push(G)}let H=Z.join(`
|
|
7452
7452
|
|
|
7453
|
-
`).trim();if(!H)throw Error("Could not extract text from the uploaded PDF");return H}finally{await B.destroy()}}fA();K7();k2();C0();import{createHash as cNw}from"crypto";var lNw=26214400,pNw=20,iNw=60000,c62=80,dNw=10,nNw={renderUrl:f.url().optional(),sourceEntityType:f.string().min(1),sourceEntityId:f.string().min(1),attachmentType:f.string().min(1),documentId:f.string().min(1).optional(),title:f.string().min(1).optional(),filename:f.string().min(1).optional(),dedupKey:f.string().min(1).optional(),replace:f.boolean().optional(),pageCount:f.number().int().min(0).optional(),maxPageCount:f.number().int().positive().optional(),maxBytes:f.number().int().positive().optional(),timeoutMs:f.number().int().positive().optional(),width:f.union([f.string(),f.number()]).optional(),height:f.union([f.string(),f.number()]).optional(),format:f.string().optional(),targetEntityType:f.string().min(1).optional(),targetEntityId:f.string().min(1).optional()},p62=f.object(nNw),QH0=p62.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 wH0 extends z6{context;renderPdf;constructor(A,Q,w={}){super(A,{schema:QH0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=w.renderPdf??HG}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??pNw,B=A.maxBytes??lNw,X=A.timeoutMs??iNw;if(A.pageCount!==void 0&&A.pageCount>$)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${$}`);let Y=await this.getDedupKey(A),Z=Ge0(A,Y),H=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let W=await this.findDocumentByDedupKey(Y,H?Z:void 0);if(W&&(!H||W.id===Z)){if(A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,W.id,A);return await this.reportProgress(w,{progress:100,message:"Reusing existing generated document"}),{success:!0,documentId:W.id,reused:!0}}}await this.reportProgress(w,{progress:20,message:"Rendering PDF document"});try{let W=await this.resolveDocumentAttachment(A,Z,{timeoutMs:X,maxBytes:B}),K=W.data;if(K.byteLength>B)throw Error(`Rendered PDF exceeds maxBytes=${B}: ${K.byteLength} bytes`);let U=jt0(K);if(U>$)throw Error(`Rendered PDF has ${U} pages, exceeding maxPageCount=${$}`);let G=U>0?U:A.pageCount;await this.reportProgress(w,{progress:70,message:"Storing PDF document"});let q=A.filename??(A.renderUrl===void 0?W.filename:`${Z}.pdf`),V=AJ.createDocumentEntity({dataUrl:Df0(K),filename:q,...A.title&&{title:A.title},...G!==void 0&&{pageCount:G},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:Y});if(await rX({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(W){let K=dA(W);throw this.logger.error("Document generation failed",{jobId:Q,error:K}),await KD({entityService:this.context.entityService,entityType:"document",id:Z,error:K}),W}}async resolveDocumentAttachment(A,Q,w){if(A.renderUrl!==void 0)return{type:"document",data:await this.renderPdf(A.renderUrl,{timeoutMs:w.timeoutMs,maxBytes:w.maxBytes,printBackground:!0,preferCSSPageSize:!0,...A.width!==void 0&&{width:A.width},...A.height!==void 0&&{height:A.height},...A.format!==void 0&&{format:A.format}}),mimeType:"application/pdf",filename:A.filename??`${Q}.pdf`};let $=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}=p6(B.content),Y=Array.isArray(X.documents)?X.documents.filter(oNw):[],Z=$.replace?await this.removeReferencesForSameSourceAttachment(Y,w,$):Y,H=Z.some((W)=>W.id===w)?Z:[...Z,{id:w}];await this.context.entityService.updateEntity({entity:{...B,content:u4(B.content,"documents",H)}})}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||!sNw(X,w))$.push(B)}return $}}function Ge0(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 rNw(B)}function rNw(A){let Q=q1(A.replace(/[/:]+/g," "))||`document-${l62(A)}`;if(Q.length<=c62)return Q;let w=`-${l62(A)}`;return`${Q.slice(0,c62-w.length).replace(/-+$/g,"")}${w}`}function l62(A){return cNw("sha256").update(A).digest("hex").slice(0,dNw)}function oNw(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function sNw(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var i62={name:"@brains/document-plugin",version:"0.2.0-alpha.
|
|
7453
|
+
`).trim();if(!H)throw Error("Could not extract text from the uploaded PDF");return H}finally{await B.destroy()}}fA();K7();k2();C0();import{createHash as cNw}from"crypto";var lNw=26214400,pNw=20,iNw=60000,c62=80,dNw=10,nNw={renderUrl:f.url().optional(),sourceEntityType:f.string().min(1),sourceEntityId:f.string().min(1),attachmentType:f.string().min(1),documentId:f.string().min(1).optional(),title:f.string().min(1).optional(),filename:f.string().min(1).optional(),dedupKey:f.string().min(1).optional(),replace:f.boolean().optional(),pageCount:f.number().int().min(0).optional(),maxPageCount:f.number().int().positive().optional(),maxBytes:f.number().int().positive().optional(),timeoutMs:f.number().int().positive().optional(),width:f.union([f.string(),f.number()]).optional(),height:f.union([f.string(),f.number()]).optional(),format:f.string().optional(),targetEntityType:f.string().min(1).optional(),targetEntityId:f.string().min(1).optional()},p62=f.object(nNw),QH0=p62.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 wH0 extends z6{context;renderPdf;constructor(A,Q,w={}){super(A,{schema:QH0,jobTypeName:"document-generate"});this.context=Q,this.renderPdf=w.renderPdf??HG}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??pNw,B=A.maxBytes??lNw,X=A.timeoutMs??iNw;if(A.pageCount!==void 0&&A.pageCount>$)throw Error(`Refusing to render ${A.pageCount} page PDF; maxPageCount=${$}`);let Y=await this.getDedupKey(A),Z=Ge0(A,Y),H=A.documentId!==void 0||A.filename!==void 0;if(A.replace!==!0){let W=await this.findDocumentByDedupKey(Y,H?Z:void 0);if(W&&(!H||W.id===Z)){if(A.targetEntityType&&A.targetEntityId)await this.attachDocumentToTarget(A.targetEntityType,A.targetEntityId,W.id,A);return await this.reportProgress(w,{progress:100,message:"Reusing existing generated document"}),{success:!0,documentId:W.id,reused:!0}}}await this.reportProgress(w,{progress:20,message:"Rendering PDF document"});try{let W=await this.resolveDocumentAttachment(A,Z,{timeoutMs:X,maxBytes:B}),K=W.data;if(K.byteLength>B)throw Error(`Rendered PDF exceeds maxBytes=${B}: ${K.byteLength} bytes`);let U=jt0(K);if(U>$)throw Error(`Rendered PDF has ${U} pages, exceeding maxPageCount=${$}`);let G=U>0?U:A.pageCount;await this.reportProgress(w,{progress:70,message:"Storing PDF document"});let q=A.filename??(A.renderUrl===void 0?W.filename:`${Z}.pdf`),V=AJ.createDocumentEntity({dataUrl:Df0(K),filename:q,...A.title&&{title:A.title},...G!==void 0&&{pageCount:G},status:"draft",sourceEntityType:A.sourceEntityType,sourceEntityId:A.sourceEntityId,attachmentType:A.attachmentType,dedupKey:Y});if(await rX({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(W){let K=dA(W);throw this.logger.error("Document generation failed",{jobId:Q,error:K}),await KD({entityService:this.context.entityService,entityType:"document",id:Z,error:K}),W}}async resolveDocumentAttachment(A,Q,w){if(A.renderUrl!==void 0)return{type:"document",data:await this.renderPdf(A.renderUrl,{timeoutMs:w.timeoutMs,maxBytes:w.maxBytes,printBackground:!0,preferCSSPageSize:!0,...A.width!==void 0&&{width:A.width},...A.height!==void 0&&{height:A.height},...A.format!==void 0&&{format:A.format}}),mimeType:"application/pdf",filename:A.filename??`${Q}.pdf`};let $=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}=p6(B.content),Y=Array.isArray(X.documents)?X.documents.filter(oNw):[],Z=$.replace?await this.removeReferencesForSameSourceAttachment(Y,w,$):Y,H=Z.some((W)=>W.id===w)?Z:[...Z,{id:w}];await this.context.entityService.updateEntity({entity:{...B,content:u4(B.content,"documents",H)}})}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||!sNw(X,w))$.push(B)}return $}}function Ge0(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 rNw(B)}function rNw(A){let Q=q1(A.replace(/[/:]+/g," "))||`document-${l62(A)}`;if(Q.length<=c62)return Q;let w=`-${l62(A)}`;return`${Q.slice(0,c62-w.length).replace(/-+$/g,"")}${w}`}function l62(A){return cNw("sha256").update(A).digest("hex").slice(0,dNw)}function oNw(A){return typeof A==="object"&&A!==null&&"id"in A&&typeof A.id==="string"&&A.id.length>0}function sNw(A,Q){return A.metadata.sourceEntityType===Q.sourceEntityType&&A.metadata.sourceEntityId===Q.sourceEntityId&&A.metadata.attachmentType===Q.attachmentType}var i62={name:"@brains/document-plugin",version:"0.2.0-alpha.169",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 tNw=`data:application/pdf;base64,${Buffer.from(`%PDF-1.4
|
|
7454
7454
|
% Pending document placeholder
|
|
7455
7455
|
%%EOF
|
|
7456
7456
|
`).toString("base64")}`,eNw=f.object({}).catchall(f.unknown()).transform(()=>({})),De0={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function Ajw(A,Q){let w=A.title?.trim();if(w)return w;return Q.replace(/\.[^.]+$/,"").trim()||Q}function Qjw(A,Q){return`data:${A};base64,${Q.toString("base64")}`}function wjw(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 qe0 extends Uw{entityType=AJ.entityType;schema=jE;adapter=AJ;pluginContext;constructor(){super("document",i62,{},eNw)}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 wH0(this.logger.child("DocumentGenerationJobHandler"),A))}async interceptCreate(A){let Q=this.pluginContext;if(A.from?.kind===De0.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=QH0.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??Ge0(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!==De0.refKind)return{kind:"handled",result:{success:!1,error:"Unsupported upload ref kind"}};let $;try{$=await Q.uploads.scoped(De0).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=Ajw(A,$.record.filename),X=q1(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=AJ.createDocumentEntity({dataUrl:Qjw($.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}`}),H=await Q.entityService.createEntity({entity:{id:X,...Z,created:Y,updated:Y},options:{deduplicateId:!0}});return{kind:"handled",result:{success:!0,data:{entityId:H.entityId,status:"created",attachment:wjw({entityId:H.entityId,filename:$.record.filename})}}}}async createPendingDocument(A,Q){let w=new Date().toISOString(),$=AJ.createDocumentEntity({dataUrl:tNw,filename:Q.filename,title:Q.title,status:"pending",sourceEntityType:Q.sourceEntityType,sourceEntityId:Q.sourceEntityId,attachmentType:Q.attachmentType,dedupKey:Q.dedupKey});await O_({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 ze0(){return new qe0}fA();C0();fA();C0();var d62=f.enum(["generating","failed"]),$jw=f.enum(["generating","failed"]),PL=f.object({title:f.string().optional(),status:d62.optional(),error:f.string().optional()}),Bjw=f.object({title:f.string(),status:d62.optional(),error:f.string().optional()}),Xjw=f.object({title:f.string(),status:$jw.optional(),error:f.string().optional()}),ML=TQ.extend({entityType:f.literal("note"),metadata:Xjw}),Yjw=ML.extend({frontmatter:PL,body:f.string()});fA();C0();var Zjw=f.record(f.string(),f.unknown());class Ve0 extends r2{constructor(){super({entityType:"note",purpose:"A short, free-form captured thought, reference, or snippet the user wants to keep.",schema:ML,frontmatterSchema:PL})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,PL);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,PL)}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,Zjw);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 BJ=new Ve0;C0();var Je0=f.object({defaultPrompt:f.string().default("Create a note summarizing key concepts from my knowledge base")});C0();fA();var n62=f.object({title:f.string().max(80).describe("A clear, descriptive title for the note (3-8 words)"),body:f.string().describe("Note content in markdown format with clear organization and structure")}),Fe0=s1({name:"note:generation",description:"Template for AI to generate notes from prompts",schema:n62,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create personal knowledge notes for research and reference.
|
|
@@ -7468,7 +7468,7 @@ title: ${JSON.stringify(A)}
|
|
|
7468
7468
|
---
|
|
7469
7469
|
|
|
7470
7470
|
${Q.trim()}
|
|
7471
|
-
`}var Ujw={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},Gjw=f.object({uploadId:f.string().min(1),entityId:f.string().min(1),title:f.string().optional()});class be0 extends z6{context;constructor(A,Q){super(A,{schema:Gjw,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(Ujw).read(A.uploadId);await this.reportProgress(w,{progress:35,message:"Extracting markdown from upload"});let B=await a62({upload:$,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress(w,{progress:80,message:"Saving imported note"});let X=new Date().toISOString(),Y=BJ.fromMarkdown(B.content),Z=await rX({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,dA($)),j8.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:u4(u4(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}}}fA();async function t62({entity:A,config:Q}){let w=ML.parse(A),$=BQ(w.content,PL);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 Le0(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:m6["ai.rizom.brain.note"],validate:!1,buildRecord:t62}}var e62={name:"@brains/note",version:"0.2.0-alpha.
|
|
7471
|
+
`}var Ujw={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},Gjw=f.object({uploadId:f.string().min(1),entityId:f.string().min(1),title:f.string().optional()});class be0 extends z6{context;constructor(A,Q){super(A,{schema:Gjw,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(Ujw).read(A.uploadId);await this.reportProgress(w,{progress:35,message:"Extracting markdown from upload"});let B=await a62({upload:$,...A.title!==void 0?{title:A.title}:{}});await this.reportProgress(w,{progress:80,message:"Saving imported note"});let X=new Date().toISOString(),Y=BJ.fromMarkdown(B.content),Z=await rX({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,dA($)),j8.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:u4(u4(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}}}fA();async function t62({entity:A,config:Q}){let w=ML.parse(A),$=BQ(w.content,PL);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 Le0(){return{entityType:"note",collection:"ai.rizom.brain.note",lexicon:m6["ai.rizom.brain.note"],validate:!1,buildRecord:t62}}var e62={name:"@brains/note",version:"0.2.0-alpha.169",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 A$2={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"},qjw=f.object({prompt:f.string()});class ke0 extends fw{entityType=BJ.entityType;schema=ML;adapter=BJ;unregisterAtprotoProjection;constructor(A={}){super("note",e62,A,Je0)}async interceptCreate(A,Q,w){if(A.from?.kind!==A$2.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(A$2).readRecord($)}catch{return{kind:"handled",result:{success:!1,error:"Upload ref not found"}}}try{if(!s62(B.mediaType))return{kind:"handled",result:{success:!1,error:"Only text, JSON, and PDF uploads can be imported as markdown notes"}};let X=Ie0({filename:B.filename,...A.title!==void 0?{title:A.title}:{}}),Y=BJ.buildStub({id:X.id,title:X.title}),Z=new Date().toISOString(),H=await w.entityService.createEntity({entity:{id:X.id,entityType:"note",content:Y.content,metadata:Y.metadata,created:Z,updated:Z},options:{deduplicateId:!0}}),W=await w.jobs.enqueue({type:"upload-import",data:{uploadId:$,entityId:H.entityId,...A.title!==void 0?{title:A.title}:{}}});return{kind:"handled",result:{success:!0,data:{entityId:H.entityId,status:"generating",jobId:W}}}}catch(X){return{kind:"handled",result:{success:!1,error:X instanceof Error?X.message:"Failed to import upload as markdown"}}}}createGenerationHandler(A){return new $H0(this.logger.child("NoteGenerationJobHandler"),A)}getTemplates(){return{generation:Fe0}}async onRegister(A){A.jobs.registerHandler("upload-import",new be0(this.logger.child("UploadMarkdownImportJobHandler"),A)),A.eval.registerHandler("generateNote",async(Q)=>{let w=qjw.parse(Q);return A.ai.generate({prompt:w.prompt,templateName:"note:generation"})}),this.unregisterAtprotoProjection=NB.getInstance().register(Le0())}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 zM(A={}){return new ke0(A)}fA();C0();fA();var Q$2=f.object({ref:f.string(),label:f.string()}),w$2=f.enum(["pending","draft","published"]),zjw=f.enum(["pending","draft","published"]),as=f.object({status:w$2,title:f.string(),url:f.string().url(),description:f.string().optional(),domain:f.string(),capturedAt:f.string().datetime(),source:Q$2}),Vjw=as.pick({title:!0,status:!0}),Jjw=f.object({title:f.string(),status:zjw}),VM=TQ.extend({entityType:f.literal("link"),metadata:Jjw});k2();C0();C0();var _e0=f.object({enableSummarization:f.boolean().default(!0).describe("Generate AI summaries for captured links"),jinaApiKey:f.string().optional().describe("Jina Reader API key for higher rate limits (500 RPM vs 20 RPM without key)")});fA();class OL extends r2{constructor(){super({entityType:"link",purpose:"A saved external URL or web resource captured for later reference.",schema:VM,frontmatterSchema:as})}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,as),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 mE=new OL;fA();C0();var Fjw=f.object({success:f.boolean().describe("Set to true if you can extract meaningful content. Set to false only if the provided content is empty, just an error message, or otherwise unusable."),error:f.string().describe("If success is false, explain why content could not be extracted. Use an empty string when success is true."),title:f.string().max(80).describe("The page title - extract from the content or create a descriptive one. Leave empty string if success is false."),description:f.string().describe("A one-sentence description of what the page is about. Leave empty string if success is false."),summary:f.string().describe("A 1-2 paragraph summary of the main content. Leave empty string if success is false.")}),$$2=s1({name:"link:extraction",description:"Extract structured content from webpage markdown",dataSourceId:"shell:ai-content",schema:Fjw,basePrompt:`You are an expert at extracting key information from webpage content.
|
|
7472
7472
|
|
|
7473
7473
|
You will receive webpage content in markdown format. Your job is to extract structured information from it.
|
|
7474
7474
|
|
|
@@ -7490,7 +7490,7 @@ Accuracy rules:
|
|
|
7490
7490
|
|
|
7491
7491
|
`))return{success:!1,error:Y.trim(),errorType:"fetch_failed"};return{success:!0,content:Y}}catch(w){return this.handleFetchError(w,A)}}handleHttpError(A,Q){if(A===400)return{success:!1,error:`Invalid or non-existent URL: ${Q}`,errorType:"url_not_found"};if(A===404)return{success:!1,error:`Page not found: ${Q}`,errorType:"url_not_found"};if(A>=500)return{success:!1,error:`Server error while fetching ${Q}`,errorType:"url_unreachable"};return{success:!1,error:`HTTP ${A} error while fetching ${Q}`,errorType:"fetch_failed"}}handleFetchError(A,Q){if(A instanceof Error){if(A.name==="AbortError")return{success:!1,error:`Request timeout while fetching ${Q}`,errorType:"url_unreachable"};if(A.message.includes("ENOTFOUND")||A.message.includes("getaddrinfo"))return{success:!1,error:`Domain not found: ${new URL(Q).hostname}`,errorType:"url_not_found"};if(A.message.includes("ECONNREFUSED")||A.message.includes("ETIMEDOUT"))return{success:!1,error:`Could not connect to ${Q}`,errorType:"url_unreachable"};return{success:!1,error:`Failed to fetch ${Q}: ${A.message}`,errorType:"fetch_failed"}}return{success:!1,error:`Unknown error fetching ${Q}`,errorType:"fetch_failed"}}}import{createHash as Njw}from"crypto";class xL{static URL_PATTERN=/https?:\/\/[^\s<>"{}|\\^`[\]]+?(?=[,;:\s]|$)/gi;static extractUrls(A){let Q=A.match(xL.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=Njw("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}}}fA();C0();Q$();var jjw=f.object({interfaceId:f.string().optional(),userId:f.string().optional(),channelId:f.string().optional(),channelName:f.string().optional(),timestamp:f.string().optional()}),Pjw=f.object({url:f.url(),metadata:jjw.optional()}),hb8=f.object({success:f.boolean(),entityId:f.string().optional(),title:f.string().optional(),url:f.string().optional(),status:f.enum(["pending","draft","published"]).optional(),error:f.string().optional()});class XH0 extends z6{context;linkAdapter;urlFetcher;constructor(A,Q,w){super(A,{schema:Pjw,jobTypeName:"link-capture"});this.context=Q,this.linkAdapter=new OL,this.urlFetcher=new uE(w?.jinaApiKey?{jinaApiKey:w.jinaApiKey}:void 0)}async process(A,Q,w){let{url:$,metadata:B}=A;try{await w.report({progress:Zw.START,total:100,message:"Starting link capture"});let X=xL.generateEntityId($);await w.report({progress:Zw.INIT,total:100,message:"Checking for existing link"});let Y=await this.context.entityService.getEntity({entityType:"link",id:X});if(Y){let{frontmatter:q}=this.linkAdapter.parseLinkContent(Y.content),V=Y.metadata.status;if(V!=="pending")return this.logger.info("Link already captured, returning existing",{url:$,entityId:X}),{success:!0,entityId:Y.id,title:q.title,url:$,status:V};this.logger.info("Pending link exists, completing extraction",{url:$,entityId:X})}let Z=this.resolveSource(B),H=new Date().toISOString();await w.report({progress:Zw.FETCH,total:100,message:"Fetching webpage content"});let W=await this.urlFetcher.fetch($);if(!W.success){if(W.errorType==="url_not_found"||W.errorType==="url_unreachable"){this.logger.warn("Link URL not accessible",{url:$,errorType:W.errorType,error:W.error});let q=new URL($).hostname,V=`Could not capture link: ${W.error}`,J=this.linkAdapter.createLinkContent({status:"pending",title:q,url:$,description:V,summary:V,domain:q,capturedAt:H,source:Z});return await rX({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:J,metadata:{status:"pending",title:q}}}),{success:!1,entityId:X,title:q,url:$,status:"pending",error:V}}}await w.report({progress:Zw.PROCESS,total:100,message:"Extracting content with AI"});let K=await this.context.ai.generate({templateName:"link:extraction",prompt:W.success?`Extract structured information from this webpage content:
|
|
7492
7492
|
|
|
7493
|
-
${W.content}`:`The URL ${$} could not be fetched. Return success: false with error: "${W.error}"`,data:{url:$,hasContent:W.success},interfacePermissionGrant:"public"});if(this.logger.debug("AI extraction result",{result:K}),await w.report({progress:Zw.EXTRACT,total:100,message:"Processing extraction results"}),K.success===!1||!K.title||!K.description||!K.summary){let q=K.title||new URL($).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:$}),await w.report({progress:Zw.SAVE,total:100,message:"Saving link as pending"});let V=this.linkAdapter.createLinkContent({status:"pending",title:q,url:$,description:K.description,summary:K.summary,domain:new URL($).hostname,capturedAt:H,source:Z}),J=await rX({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:V,metadata:{status:"pending",title:q}}});return await w.report({progress:Zw.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:J.entityId,title:q,url:$,status:"pending"}}await w.report({progress:Zw.SAVE,total:100,message:`Saving link: "${K.title}"`});let U=this.linkAdapter.createLinkContent({status:"draft",title:K.title,url:$,description:K.description,summary:K.summary,domain:new URL($).hostname,capturedAt:H,source:Z}),G=await rX({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:U,metadata:{status:"draft",title:K.title}}});return await w.report({progress:Zw.COMPLETE,total:100,message:`Link captured: "${K.title}"`}),{success:!0,entityId:G.entityId,title:K.title,url:$,status:"draft"}}catch(X){return this.logger.error("Link capture job failed",{error:X,jobId:Q,data:A}),j8.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 Y$2({entity:A,config:Q}){let w=VM.parse(A),{frontmatter:$,summary:B}=mE.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 xe0(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:m6["ai.rizom.brain.link"],validate:!1,buildRecord:Y$2}}var Z$2={name:"@brains/link",version:"0.2.0-alpha.
|
|
7493
|
+
${W.content}`:`The URL ${$} could not be fetched. Return success: false with error: "${W.error}"`,data:{url:$,hasContent:W.success},interfacePermissionGrant:"public"});if(this.logger.debug("AI extraction result",{result:K}),await w.report({progress:Zw.EXTRACT,total:100,message:"Processing extraction results"}),K.success===!1||!K.title||!K.description||!K.summary){let q=K.title||new URL($).hostname;this.logger.info("Incomplete extraction, saving as pending",{url:$}),await w.report({progress:Zw.SAVE,total:100,message:"Saving link as pending"});let V=this.linkAdapter.createLinkContent({status:"pending",title:q,url:$,description:K.description,summary:K.summary,domain:new URL($).hostname,capturedAt:H,source:Z}),J=await rX({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:V,metadata:{status:"pending",title:q}}});return await w.report({progress:Zw.COMPLETE,total:100,message:"Link saved (pending)"}),{success:!0,entityId:J.entityId,title:q,url:$,status:"pending"}}await w.report({progress:Zw.SAVE,total:100,message:`Saving link: "${K.title}"`});let U=this.linkAdapter.createLinkContent({status:"draft",title:K.title,url:$,description:K.description,summary:K.summary,domain:new URL($).hostname,capturedAt:H,source:Z}),G=await rX({entityService:this.context.entityService,entity:{id:X,entityType:"link",content:U,metadata:{status:"draft",title:K.title}}});return await w.report({progress:Zw.COMPLETE,total:100,message:`Link captured: "${K.title}"`}),{success:!0,entityId:G.entityId,title:K.title,url:$,status:"draft"}}catch(X){return this.logger.error("Link capture job failed",{error:X,jobId:Q,data:A}),j8.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 Y$2({entity:A,config:Q}){let w=VM.parse(A),{frontmatter:$,summary:B}=mE.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 xe0(){return{entityType:"link",collection:"ai.rizom.brain.link",lexicon:m6["ai.rizom.brain.link"],validate:!1,buildRecord:Y$2}}var Z$2={name:"@brains/link",version:"0.2.0-alpha.169",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 Ojw=f.object({url:f.url()});class Re0 extends fw{entityType=mE.entityType;schema=VM;adapter=mE;shell;unregisterAtprotoProjection;constructor(A={}){super("link",Z$2,A,_e0)}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 XH0(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,H=this.extractFirstUrl(A.content);if(Y&&Z&&H){let W=q1(H)||q1(Y)||`${A.entityType}-${Date.now()}`,K=new Date().toISOString();return{kind:"handled",result:{success:!0,data:{entityId:(await w.entityService.createEntity({entity:{id:W,entityType:A.entityType,content:A.content,metadata:{title:Y,status:Z},created:K,updated:K}})).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 XH0(this.logger.child("LinkCaptureJobHandler"),A,this.config.jinaApiKey?{jinaApiKey:this.config.jinaApiKey}:void 0)}getTemplates(){return{extraction:$$2,"link-list":B$2,"link-detail":X$2}}getDataSources(){return[new Oe0(this.logger.child("LinksDataSource"))]}async onRegister(A){this.unregisterAtprotoProjection=NB.getInstance().register(xe0()),A.eval.registerHandler("extractContent",async(Q)=>{let{url:w}=Ojw.parse(Q),B=await new uE(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:
|
|
7494
7494
|
|
|
7495
7495
|
${B.content}`,data:{url:w,hasContent:!0},interfacePermissionGrant:"public"})})}async createPendingLink(A,Q,w,$){let B=xL.generateEntityId(A),X=new URL(A),Y=new Date().toISOString(),Z=Q?.trim()?Q.trim():X.hostname,H=this.adapter.createLinkContent({status:"pending",title:Z,url:A,description:"Link capture is in progress.",summary:`Pending link capture for ${A}.`,domain:X.hostname,capturedAt:Y,source:this.resolveSource(w)});return(await O_({entityService:$.entityService,entity:{id:B,entityType:"link",content:H,metadata:{status:"pending",title:Z},created:Y,updated:Y}})).entityId}resolveSource(A){if(A.channelId)return{ref:`matrix:${A.channelId}`,label:A.channelName??A.channelId};return{ref:`${A.interfaceType}:local`,label:A.interfaceType.toUpperCase()}}extractFirstUrl(...A){for(let Q of A){if(!Q)continue;let[w]=xL.extractUrls(Q);if(w)return w}return}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}}function f$2(A={}){return new Re0(A)}var JM=f$2;C0();var xjw=f.object({conversationId:f.string().optional(),interfaceId:f.string().optional(),userId:f.string().optional(),messageId:f.string().optional(),timestamp:f.string().optional()}),ZL8=f.object({id:f.string().optional(),metadata:xjw.optional()});fA();C0();n$();C0();fA();var H$2=f.enum(["generating","draft","published","failed"]),W$2=f.enum(["generating","draft","published","failed"]),y7=f.object({title:f.string(),slug:f.string().optional(),status:H$2,publishedAt:f.string().datetime().optional(),description:f.string(),year:f.number(),coverImageId:f.string().optional(),ogImageId:f.string().optional(),url:f.string().url().optional()}),Rjw=y7.pick({title:!0,status:!0,publishedAt:!0,year:!0}).extend({slug:f.string(),error:f.string().optional()}),vjw=f.object({title:f.string(),status:W$2,publishedAt:f.string().datetime().optional(),year:f.number(),slug:f.string(),error:f.string().optional()}),hjw=f.object({title:f.string(),slug:f.string().optional(),status:W$2,publishedAt:f.string().datetime().optional(),description:f.string(),year:f.number(),coverImageId:f.string().optional(),ogImageId:f.string().optional(),url:f.string().url().optional()}),RL=TQ.extend({entityType:f.literal("project"),metadata:vjw}),YH0=f.object({context:f.string(),problem:f.string(),solution:f.string(),outcome:f.string()}),es=RL.extend({frontmatter:hjw,body:f.string(),structuredContent:YH0.optional(),coverImageUrl:f.string().optional(),ogImageUrl:f.string().optional()}),Cjw=es.extend({url:f.string().optional(),typeLabel:f.string().optional(),coverImageUrl:f.string().optional(),ogImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()}),yjw=es.extend({url:f.string(),typeLabel:f.string(),coverImageUrl:f.string().optional(),ogImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()});fA();k2();H5();class ve0 extends Y6{constructor(){super(YH0,{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 he0=new ve0;class Ce0 extends r2{constructor(){super({entityType:"project",purpose:"A project record in the user's portfolio.",schema:RL,frontmatterSchema:y7,supportsCoverImage:!0,bodyFormatter:he0})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,y7),$={...w,slug:w.slug??A.metadata.slug};return this.buildMarkdown(Q,$)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,y7),w=Q.slug??q1(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,y7)}parseStructuredContent(A){return he0.parse(this.extractBody(A.content))}createProjectContent(A,Q){let w=he0.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 FM=new Ce0;C0();var ye0=f.looseObject({});import{jsxDEV as jH,Fragment as Ejw}from"preact/jsx-dev-runtime";var gjw=({project:A})=>{let{frontmatter:Q,url:w,coverImageUrl:$}=A;return jH(R6,{href:w,children:[$&&jH("img",{src:$,alt:Q.title,className:"w-full h-56 object-cover rounded-md mb-4"},void 0,!1,void 0,this),jH(x7,{children:Q.title},void 0,!1,void 0,this),jH("p",{className:"text-theme leading-relaxed",children:Q.description},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},ge0=({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 jH(Ejw,{children:[jH(Bw,{title:B,description:Y},void 0,!1,void 0,this),jH("div",{className:"project-list bg-theme",children:jH("div",{className:"container mx-auto px-6 md:px-12 max-w-5xl py-16 md:py-24",children:[jH("h1",{className:"text-4xl font-bold text-heading mb-12",children:B},void 0,!1,void 0,this),jH("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-8",children:A.map((Z)=>jH(gjw,{project:Z},Z.id,!1,void 0,this))},void 0,!1,void 0,this),w&&w.totalPages>1&&jH("div",{className:"mt-12",children:jH(mV,{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 W$,Fragment as K$2}from"preact/jsx-dev-runtime";var Tjw=({prevProject:A,nextProject:Q})=>{if(!A&&!Q)return null;return W$("nav",{className:"pt-12 mt-12 border-t border-theme-muted",children:W$("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[A?W$(R6,{href:A.url,variant:"compact",children:[W$("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Previous"},void 0,!1,void 0,this),W$("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:A.metadata.title},void 0,!1,void 0,this)]},void 0,!0,void 0,this):W$("div",{},void 0,!1,void 0,this),Q&&W$(R6,{href:Q.url,variant:"compact",className:"md:text-right",children:[W$("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Next"},void 0,!1,void 0,this),W$("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:Q.metadata.title},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},ZH0=({title:A,content:Q})=>{if(!Q)return null;return W$("section",{className:"mb-12",children:[W$("h2",{className:"text-2xl font-bold text-heading mb-4",children:A},void 0,!1,void 0,this),W$(i9,{markdown:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},Ee0=({project:A,prevProject:Q,nextProject:w})=>{let{frontmatter:$,structuredContent:B,metadata:X,coverImageUrl:Y}=A,Z=A.ogImageUrl??Y;return W$(K$2,{children:[W$(Bw,{title:$.title,description:$.description,...Z?{ogImage:Z}:{},ogType:"article"},void 0,!1,void 0,this),W$("article",{className:"project-detail",children:W$("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:W$("div",{className:"max-w-3xl mx-auto",children:[Y&&A.coverImageWidth&&A.coverImageHeight&&W$(TV,{src:Y,alt:$.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8 shadow-lg"},void 0,!1,void 0,this),W$("h1",{className:"text-4xl md:text-5xl font-bold text-heading leading-tight tracking-tight mb-4",children:$.title},void 0,!1,void 0,this),W$("div",{className:"flex flex-wrap items-center gap-4 text-theme-muted mb-8",children:[W$("span",{className:"text-sm",children:X.year},void 0,!1,void 0,this),$.url&&W$(K$2,{children:[W$("span",{className:"text-theme-muted",children:"|"},void 0,!1,void 0,this),W$("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),W$("p",{className:"text-lg text-theme mb-12 leading-relaxed",children:$.description},void 0,!1,void 0,this),B&&W$("div",{className:"case-study",children:[W$(ZH0,{title:"Context",content:B.context},void 0,!1,void 0,this),W$(ZH0,{title:"Problem",content:B.problem},void 0,!1,void 0,this),W$(ZH0,{title:"Solution",content:B.solution},void 0,!1,void 0,this),W$(ZH0,{title:"Outcome",content:B.outcome},void 0,!1,void 0,this)]},void 0,!0,void 0,this),W$(Tjw,{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)};C0();fA();var Sjw=f.object({title:f.string().max(80).describe("A clear, compelling project title (3-8 words). Should capture the essence of the project."),description:f.string().describe("A 1-2 sentence summary of the project for portfolio cards. Focus on the core value delivered."),context:f.string().describe("Background information: Who was the client/user? What was the situation? What constraints existed? (2-4 paragraphs)"),problem:f.string().describe("The challenge: What specific problem needed solving? What were the pain points? (2-3 paragraphs)"),solution:f.string().describe("The approach: What was built? What technologies/methods were used? How did it work? (3-5 paragraphs)"),outcome:f.string().describe("The results: What impact did this have? What metrics improved? What was learned? (2-3 paragraphs)")}),Te0=s1({name:"portfolio:generation",description:"Template for AI to generate portfolio project case studies",schema:Sjw,dataSourceId:"shell:ai-content",requiredPermission:"public",useKnowledgeContext:!0,basePrompt:`You are helping to create a professional portfolio case study based on REAL project information.
|
|
7496
7496
|
|
|
@@ -7666,7 +7666,7 @@ Use the project request as the primary source of truth. If retrieved knowledge c
|
|
|
7666
7666
|
font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
|
|
7667
7667
|
}
|
|
7668
7668
|
.printable-footer a { color: inherit; text-decoration: none; overflow-wrap: anywhere; }
|
|
7669
|
-
`}},void 0,!1,void 0,this),a9("section",{className:"project-shell",children:[a9("header",{className:"project-hero",children:[a9("div",{className:"project-index",children:[Q.brandLabel&&a9("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&a9("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a9("div",{className:"project-title-panel",children:[a9("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),a9("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&a9("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),a9("div",{className:"printable-meta",children:[Q.year&&a9("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&a9("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&&a9("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),a9(i9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&a9("footer",{className:"printable-footer",children:[a9("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?a9("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 rjw=26214400,ojw=60000;class ue0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??HG}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==WH0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let w=sjw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await pjw(njw(djw(),"brain-project-printable-"));try{let B=await zH({outputDir:$,mediaPath:`/_media/printable/project/${Q.id}`,template:D$2,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await VH({rootDir:$});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:rjw,timeoutMs:ojw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${ajw(Q)}-printable.pdf`}}finally{await X.close()}}finally{await ijw($,{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}=p6(A.content),w=y7.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 sjw(A,Q={}){let{frontmatter:w,content:$}=p6(A.content),B=y7.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 ajw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}K7();k2();C0();import{jsxDEV as APw}from"preact/jsx-dev-runtime";var KH0="og-image",tjw="portfolio:og-image",q$2=f.object({title:f.string().min(1),description:f.string().optional(),year:f.number().optional(),brandLabel:f.string().optional(),coverImageUrl:f.string().optional()}),z$2={name:tjw,pluginId:"portfolio",schema:q$2,renderers:{image:ejw}};function ejw(A){let Q=q$2.parse(A);return APw(EV,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class ce0{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!==KH0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w}=p6(Q.content),$=y7.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 YM({mediaPath:`/_media/og/project/${Q.id}`,template:z$2,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:`${QPw(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 QPw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}var V$2={name:"@brains/portfolio",version:"0.2.0-alpha.168",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 $Pw=f.object({currentPage:f.number(),totalPages:f.number(),totalItems:f.number(),pageSize:f.number(),hasNextPage:f.boolean(),hasPrevPage:f.boolean()}),BPw=f.union([f.enum(["public","shared","restricted"]),f.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),J$2=f.enum(["generating","draft","published","failed"]),XPw=f.object({title:f.string(),slug:f.string().optional(),status:J$2,publishedAt:f.string().optional(),description:f.string(),year:f.number(),coverImageId:f.string().optional(),ogImageId:f.string().optional(),url:f.url().optional()}),YPw=f.object({title:f.string(),status:J$2,publishedAt:f.string().optional(),year:f.number(),slug:f.string(),error:f.string().optional()}),ZPw=f.object({context:f.string(),problem:f.string(),solution:f.string(),outcome:f.string()}),UH0=f.object({id:f.string(),entityType:f.literal("project"),content:f.string(),created:f.string(),updated:f.string(),visibility:BPw,metadata:YPw,contentHash:f.string(),frontmatter:XPw,body:f.string(),structuredContent:ZPw.optional(),url:f.string().optional(),typeLabel:f.string().optional(),coverImageUrl:f.string().optional(),ogImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()}),fPw=f.object({projects:f.array(UH0),pageTitle:f.string().optional(),pagination:$Pw.nullable(),baseUrl:f.string().optional()}),HPw=f.object({prompt:f.string(),year:f.number()});function WPw(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 le0 extends fw{entityType="project";schema=RL;adapter=FM;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",V$2,A,ye0)}async interceptCreate(A,Q,w){if(!A.prompt||A.content)return{kind:"continue",input:A};let $=WPw(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 fH0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":s1({name:"project-list",description:"Portfolio project list page template",schema:fPw,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:ge0}}),"project-detail":s1({name:"project-detail",description:"Individual project case study template",schema:f.object({project:UH0,prevProject:UH0.nullable(),nextProject:UH0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:Ee0}}),generation:Te0}}getDataSources(){return[new HH0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",WH0,new ue0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",KH0,new ce0(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=NB.getInstance().register(me0())}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=HPw.parse(Q);return A.ai.generate({prompt:Se0(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=BQ(B.content,y7),Y=new Date().toISOString(),Z=l5(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:dA(B)}})}return{success:!0}})}}function pe0(A={}){return new le0(A)}fA();C0();n$();C0();fA();var F$2=f.enum(["available","early access","coming soon","planned"]),I$2=f.enum(["available","early access","coming soon","planned"]),b$2=f.object({title:f.string(),description:f.string()}),HK=f.object({name:f.string(),availability:F$2,order:f.number(),ogImageId:f.string().optional()}),GH0=f.object({tagline:f.string(),promise:f.string(),role:f.string(),purpose:f.string(),audience:f.string(),values:f.array(f.string()).min(1),features:f.array(b$2).min(1).max(6),story:f.string()}),X_8=HK.pick({name:!0,availability:!0,order:!0}).extend({slug:f.string()}),KPw=f.object({name:f.string(),availability:I$2,order:f.number(),slug:f.string()}),UPw=f.object({name:f.string(),availability:I$2,order:f.number(),ogImageId:f.string().optional()}),cE=TQ.extend({entityType:f.literal("product"),metadata:KPw}),DH0=cE.extend({frontmatter:UPw,body:GH0,labels:f.record(f.string(),f.string()),ogImageUrl:f.string().optional()}),GPw=DH0.extend({url:f.string().optional(),typeLabel:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),ogImageUrl:f.string().optional()});fA();k2();H5();class lE extends Y6{constructor(){super(GH0,{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 ie0 extends r2{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:cE,frontmatterSchema:HK,bodyFormatter:new lE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,HK);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,HK),w=q1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:w,availability:Q.availability,order:Q.order}}}}var qH0=new ie0;C0();fA();var L$2=f.object({title:f.string(),description:f.string()}),k$2=f.object({title:f.string(),description:f.string()}),DPw=f.object({title:f.string(),description:f.string()}),_$2=f.object({heading:f.string(),buttonText:f.string(),link:f.string()}),vL=f.object({headline:f.string(),tagline:f.string()}),qPw=f.object({title:f.string(),description:f.string()}),zH0=f.object({vision:f.string(),pillars:f.array(L$2).min(1).max(6),approach:f.array(qPw).min(1).max(6),productsIntro:f.string(),technologies:f.array(DPw).min(1).max(6),benefits:f.array(k$2).min(1).max(6),cta:_$2}),zPw=vL.pick({headline:!0}).extend({slug:f.string()}),VPw=f.object({headline:f.string(),slug:f.string()}),JPw=f.object({headline:f.string(),tagline:f.string()}),pE=TQ.extend({entityType:f.literal("products-overview"),metadata:VPw}),de0=pE.extend({frontmatter:JPw,body:zH0,labels:f.record(f.string(),f.string())});fA();k2();H5();class iE extends Y6{constructor(){super(zH0,{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 ne0 extends r2{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:pE,frontmatterSchema:vL,bodyFormatter:new iE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,vL);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,vL),w=q1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:w}}}}var re0=new ne0;fA();C0();var FPw=f.object({entityType:f.string(),query:f.object({id:f.string().optional()}).optional()});function N$2(A,Q){let w=BQ(A.content,HK),$=Q.parse(w.content),B=Q.getLabels();return DH0.parse({...A,frontmatter:w.metadata,body:$,labels:B})}function j$2(A,Q){let w=BQ(A.content,vL),$=Q.parse(w.content),B=Q.getLabels();return de0.parse({...A,frontmatter:w.metadata,body:$,labels:B})}class VH0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new iE;productFormatter=new lE;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,w){let $=FPw.parse(A),B=w.entityService;if($.entityType==="products-overview"){let W=(await B.listEntities({entityType:"products-overview",options:{limit:1}}))[0];if(!W)throw Error("Products overview entity not found");let K=j$2(W,this.overviewFormatter);return Q.parse(K)}if($.query?.id){let W=(await B.listEntities({entityType:"product",options:{filter:{metadata:{slug:$.query.id}},limit:1}}))[0];if(!W)throw Error(`Product not found: ${$.query.id}`);return Q.parse({product:N$2(W,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:j$2(Z,this.overviewFormatter),products:Y.map((H)=>N$2(H,this.productFormatter))})}}import{jsxDEV as I1,Fragment as LPw}from"preact/jsx-dev-runtime";var P$2=({overview:A,products:Q})=>{let{frontmatter:w,body:$,labels:B}=A;return I1(LPw,{children:[I1(Bw,{title:w.headline,description:w.tagline},void 0,!1,void 0,this),I1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[I1("style",{children:`
|
|
7669
|
+
`}},void 0,!1,void 0,this),a9("section",{className:"project-shell",children:[a9("header",{className:"project-hero",children:[a9("div",{className:"project-index",children:[Q.brandLabel&&a9("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),Q.year&&a9("span",{className:"project-year",children:Q.year},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a9("div",{className:"project-title-panel",children:[a9("span",{className:"printable-kind",children:"Case study dossier"},void 0,!1,void 0,this),a9("h1",{className:"printable-title",children:Q.title},void 0,!1,void 0,this),Q.description&&a9("p",{className:"printable-description",children:Q.description},void 0,!1,void 0,this),a9("div",{className:"printable-meta",children:[Q.year&&a9("span",{children:Q.year},void 0,!1,void 0,this),Q.url&&a9("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&&a9("img",{className:"printable-cover",src:Q.coverImageUrl,alt:""},void 0,!1,void 0,this),a9(i9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this),(Boolean(Q.canonicalUrl)||Boolean(Q.url)||Boolean(Q.brandLabel))&&a9("footer",{className:"printable-footer",children:[a9("span",{children:Q.brandLabel??"Project printable"},void 0,!1,void 0,this),Q.canonicalUrl||Q.url?a9("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 rjw=26214400,ojw=60000;class ue0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??HG}async resolve(A){if(A.sourceEntityType!=="project"||A.attachmentType!==WH0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let w=sjw(Q,{brandLabel:this.resolveBrandLabel(),coverImageUrl:await this.resolveCoverImageUrl(Q)}),$=await pjw(njw(djw(),"brain-project-printable-"));try{let B=await zH({outputDir:$,mediaPath:`/_media/printable/project/${Q.id}`,template:D$2,format:"pdf",content:w,siteConfig:{title:w.title,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await VH({rootDir:$});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:rjw,timeoutMs:ojw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${ajw(Q)}-printable.pdf`}}finally{await X.close()}}finally{await ijw($,{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}=p6(A.content),w=y7.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 sjw(A,Q={}){let{frontmatter:w,content:$}=p6(A.content),B=y7.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 ajw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}K7();k2();C0();import{jsxDEV as APw}from"preact/jsx-dev-runtime";var KH0="og-image",tjw="portfolio:og-image",q$2=f.object({title:f.string().min(1),description:f.string().optional(),year:f.number().optional(),brandLabel:f.string().optional(),coverImageUrl:f.string().optional()}),z$2={name:tjw,pluginId:"portfolio",schema:q$2,renderers:{image:ejw}};function ejw(A){let Q=q$2.parse(A);return APw(EV,{brandLabel:Q.brandLabel??Q.title,eyebrow:"Project",title:Q.title,subtitle:Q.description,tag:Q.year},void 0,!1,void 0,this)}class ce0{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!==KH0)return;let Q=await this.context.entityService.getEntity({entityType:"project",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w}=p6(Q.content),$=y7.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 YM({mediaPath:`/_media/og/project/${Q.id}`,template:z$2,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:`${QPw(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 QPw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.title)}var V$2={name:"@brains/portfolio",version:"0.2.0-alpha.169",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 $Pw=f.object({currentPage:f.number(),totalPages:f.number(),totalItems:f.number(),pageSize:f.number(),hasNextPage:f.boolean(),hasPrevPage:f.boolean()}),BPw=f.union([f.enum(["public","shared","restricted"]),f.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),J$2=f.enum(["generating","draft","published","failed"]),XPw=f.object({title:f.string(),slug:f.string().optional(),status:J$2,publishedAt:f.string().optional(),description:f.string(),year:f.number(),coverImageId:f.string().optional(),ogImageId:f.string().optional(),url:f.url().optional()}),YPw=f.object({title:f.string(),status:J$2,publishedAt:f.string().optional(),year:f.number(),slug:f.string(),error:f.string().optional()}),ZPw=f.object({context:f.string(),problem:f.string(),solution:f.string(),outcome:f.string()}),UH0=f.object({id:f.string(),entityType:f.literal("project"),content:f.string(),created:f.string(),updated:f.string(),visibility:BPw,metadata:YPw,contentHash:f.string(),frontmatter:XPw,body:f.string(),structuredContent:ZPw.optional(),url:f.string().optional(),typeLabel:f.string().optional(),coverImageUrl:f.string().optional(),ogImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()}),fPw=f.object({projects:f.array(UH0),pageTitle:f.string().optional(),pagination:$Pw.nullable(),baseUrl:f.string().optional()}),HPw=f.object({prompt:f.string(),year:f.number()});function WPw(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 le0 extends fw{entityType="project";schema=RL;adapter=FM;unregisterAtprotoProjection;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("portfolio",V$2,A,ye0)}async interceptCreate(A,Q,w){if(!A.prompt||A.content)return{kind:"continue",input:A};let $=WPw(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 fH0(this.logger.child("ProjectGenerationJobHandler"),A)}getTemplates(){return{"project-list":s1({name:"project-list",description:"Portfolio project list page template",schema:fPw,dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:ge0}}),"project-detail":s1({name:"project-detail",description:"Individual project case study template",schema:f.object({project:UH0,prevProject:UH0.nullable(),nextProject:UH0.nullable()}),dataSourceId:"portfolio:entities",requiredPermission:"public",layout:{component:Ee0}}),generation:Te0}}getDataSources(){return[new HH0(this.logger.child("ProjectDataSource"))]}async onRegister(A){this.registerEvalHandlers(A),this.unregisterPrintableAttachmentProvider=A.attachments.register("project",WH0,new ue0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("project",KH0,new ce0(A)),this.deferPublishRegistration(A),this.subscribeToPublishExecute(A),this.unregisterAtprotoProjection=NB.getInstance().register(me0())}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=HPw.parse(Q);return A.ai.generate({prompt:Se0(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=BQ(B.content,y7),Y=new Date().toISOString(),Z=l5(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:dA(B)}})}return{success:!0}})}}function pe0(A={}){return new le0(A)}fA();C0();n$();C0();fA();var F$2=f.enum(["available","early access","coming soon","planned"]),I$2=f.enum(["available","early access","coming soon","planned"]),b$2=f.object({title:f.string(),description:f.string()}),HK=f.object({name:f.string(),availability:F$2,order:f.number(),ogImageId:f.string().optional()}),GH0=f.object({tagline:f.string(),promise:f.string(),role:f.string(),purpose:f.string(),audience:f.string(),values:f.array(f.string()).min(1),features:f.array(b$2).min(1).max(6),story:f.string()}),X_8=HK.pick({name:!0,availability:!0,order:!0}).extend({slug:f.string()}),KPw=f.object({name:f.string(),availability:I$2,order:f.number(),slug:f.string()}),UPw=f.object({name:f.string(),availability:I$2,order:f.number(),ogImageId:f.string().optional()}),cE=TQ.extend({entityType:f.literal("product"),metadata:KPw}),DH0=cE.extend({frontmatter:UPw,body:GH0,labels:f.record(f.string(),f.string()),ogImageUrl:f.string().optional()}),GPw=DH0.extend({url:f.string().optional(),typeLabel:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),ogImageUrl:f.string().optional()});fA();k2();H5();class lE extends Y6{constructor(){super(GH0,{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 ie0 extends r2{constructor(){super({entityType:"product",purpose:"A product entry in the portfolio.",schema:cE,frontmatterSchema:HK,bodyFormatter:new lE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,HK);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,HK),w=q1(Q.name);return{content:A,entityType:"product",metadata:{name:Q.name,slug:w,availability:Q.availability,order:Q.order}}}}var qH0=new ie0;C0();fA();var L$2=f.object({title:f.string(),description:f.string()}),k$2=f.object({title:f.string(),description:f.string()}),DPw=f.object({title:f.string(),description:f.string()}),_$2=f.object({heading:f.string(),buttonText:f.string(),link:f.string()}),vL=f.object({headline:f.string(),tagline:f.string()}),qPw=f.object({title:f.string(),description:f.string()}),zH0=f.object({vision:f.string(),pillars:f.array(L$2).min(1).max(6),approach:f.array(qPw).min(1).max(6),productsIntro:f.string(),technologies:f.array(DPw).min(1).max(6),benefits:f.array(k$2).min(1).max(6),cta:_$2}),zPw=vL.pick({headline:!0}).extend({slug:f.string()}),VPw=f.object({headline:f.string(),slug:f.string()}),JPw=f.object({headline:f.string(),tagline:f.string()}),pE=TQ.extend({entityType:f.literal("products-overview"),metadata:VPw}),de0=pE.extend({frontmatter:JPw,body:zH0,labels:f.record(f.string(),f.string())});fA();k2();H5();class iE extends Y6{constructor(){super(zH0,{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 ne0 extends r2{constructor(){super({entityType:"products-overview",purpose:"A high-level overview of the product portfolio.",schema:pE,frontmatterSchema:vL,bodyFormatter:new iE})}toMarkdown(A){let Q=this.extractBody(A.content);try{let w=this.parseFrontMatter(A.content,vL);return this.buildMarkdown(Q,w)}catch{return Q}}fromMarkdown(A){let Q=this.parseFrontMatter(A,vL),w=q1(Q.headline);return{content:A,entityType:"products-overview",metadata:{headline:Q.headline,slug:w}}}}var re0=new ne0;fA();C0();var FPw=f.object({entityType:f.string(),query:f.object({id:f.string().optional()}).optional()});function N$2(A,Q){let w=BQ(A.content,HK),$=Q.parse(w.content),B=Q.getLabels();return DH0.parse({...A,frontmatter:w.metadata,body:$,labels:B})}function j$2(A,Q){let w=BQ(A.content,vL),$=Q.parse(w.content),B=Q.getLabels();return de0.parse({...A,frontmatter:w.metadata,body:$,labels:B})}class VH0{logger;id="products:entities";name="Products Entity DataSource";description="Fetches products and overview for the products page";overviewFormatter=new iE;productFormatter=new lE;constructor(A){this.logger=A,this.logger.debug("ProductsDataSource initialized")}async fetch(A,Q,w){let $=FPw.parse(A),B=w.entityService;if($.entityType==="products-overview"){let W=(await B.listEntities({entityType:"products-overview",options:{limit:1}}))[0];if(!W)throw Error("Products overview entity not found");let K=j$2(W,this.overviewFormatter);return Q.parse(K)}if($.query?.id){let W=(await B.listEntities({entityType:"product",options:{filter:{metadata:{slug:$.query.id}},limit:1}}))[0];if(!W)throw Error(`Product not found: ${$.query.id}`);return Q.parse({product:N$2(W,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:j$2(Z,this.overviewFormatter),products:Y.map((H)=>N$2(H,this.productFormatter))})}}import{jsxDEV as I1,Fragment as LPw}from"preact/jsx-dev-runtime";var P$2=({overview:A,products:Q})=>{let{frontmatter:w,body:$,labels:B}=A;return I1(LPw,{children:[I1(Bw,{title:w.headline,description:w.tagline},void 0,!1,void 0,this),I1("header",{className:"relative w-full min-h-[80vh] flex items-end px-6 md:px-12 bg-brand-dark overflow-hidden",children:[I1("style",{children:`
|
|
7670
7670
|
@keyframes wave-drift {
|
|
7671
7671
|
from { transform: translateX(0); }
|
|
7672
7672
|
to { transform: translateX(-50%); }
|
|
@@ -7861,7 +7861,7 @@ Use the project request as the primary source of truth. If retrieved knowledge c
|
|
|
7861
7861
|
font: 10px/1.45 var(--font-mono, "JetBrains Mono", ui-monospace, monospace);
|
|
7862
7862
|
}
|
|
7863
7863
|
`}},void 0,!1,void 0,this),PH("section",{className:"product-shell",children:[PH("header",{className:"product-hero",children:[Q.brandLabel&&PH("p",{className:"printable-kicker",children:Q.brandLabel},void 0,!1,void 0,this),PH("h1",{className:"printable-title",children:Q.name},void 0,!1,void 0,this),Q.availability&&PH("div",{className:"printable-meta",children:PH("span",{children:Q.availability},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),PH("div",{className:"product-body-wrap",children:[PH("aside",{className:"product-rail","aria-hidden":"true",children:PH("p",{className:"product-rail-label",children:"Product brief / capabilities"},void 0,!1,void 0,this)},void 0,!1,void 0,this),PH(i9,{markdown:Q.body,className:"printable-body"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Q.brandLabel&&PH("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 xPw=26214400,RPw=60000;class se0{metadata={outputEntityType:"document"};context;renderPdf;constructor(A,Q={}){this.context=A,this.renderPdf=Q.renderPdf??HG}async resolve(A){if(A.sourceEntityType!=="product"||A.attachmentType!==JH0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let w=vPw(Q,{brandLabel:this.resolveBrandLabel()}),$=await jPw(OPw(MPw(),"brain-product-printable-"));try{let B=await zH({outputDir:$,mediaPath:`/_media/printable/product/${Q.id}`,template:x$2,format:"pdf",content:w,siteConfig:{title:w.name,themeMode:"light"},themeCSS:this.context.themeCSS}),X=await VH({rootDir:$});try{return{type:"document",data:await this.renderPdf(X.urlFor(B.urlPath),{maxBytes:xPw,timeoutMs:RPw,printBackground:!0,preferCSSPageSize:!0}),mimeType:"application/pdf",filename:`${hPw(Q)}-printable.pdf`}}finally{await X.close()}}finally{await PPw($,{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 vPw(A,Q={}){let{frontmatter:w,content:$}=p6(A.content),B=HK.parse(w);return{name:B.name,body:$,availability:B.availability,...Q.brandLabel?{brandLabel:Q.brandLabel}:{}}}function hPw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.name)}K7();k2();C0();import{jsxDEV as gPw}from"preact/jsx-dev-runtime";var FH0="og-image",CPw="products:og-image",R$2=f.object({name:f.string().min(1),tagline:f.string().optional(),availability:f.string().optional(),brandLabel:f.string().optional()}),v$2={name:CPw,pluginId:"products",schema:R$2,renderers:{image:yPw}};function yPw(A){let Q=R$2.parse(A);return gPw(EV,{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 ae0{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!==FH0)return;let Q=await this.context.entityService.getEntity({entityType:"product",id:A.sourceEntityId});if(!Q)return;let{frontmatter:w,content:$}=p6(Q.content),B=HK.parse(w),X=EPw($,"Tagline"),Y=this.resolveBrandLabel(),Z={name:B.name,availability:B.availability,...X?{tagline:X}:{},...Y?{brandLabel:Y}:{}};return{type:"image",data:await YM({mediaPath:`/_media/og/product/${Q.id}`,template:v$2,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:`${TPw(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 EPw(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(`
|
|
7864
|
-
`).trim();return X.length>0?X:void 0}function TPw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.name)}var h$2={name:"@brains/products",version:"0.2.0-alpha.
|
|
7864
|
+
`).trim();return X.length>0?X:void 0}function TPw(A){let Q=A.metadata.slug;return Q.length>0?Q:q1(A.metadata.name)}var h$2={name:"@brains/products",version:"0.2.0-alpha.169",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 mPw=f.union([f.enum(["public","shared","restricted"]),f.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),C$2=f.object({id:f.string(),entityType:f.string(),content:f.string(),created:f.string(),updated:f.string(),visibility:mPw,metadata:f.record(f.string(),f.unknown()),contentHash:f.string()}),y$2=f.enum(["available","early access","coming soon","planned"]),uPw=f.object({title:f.string(),description:f.string()}),cPw=f.object({name:f.string(),availability:y$2,order:f.number(),ogImageId:f.string().optional()}),lPw=f.object({tagline:f.string(),promise:f.string(),role:f.string(),purpose:f.string(),audience:f.string(),values:f.array(f.string()).min(1),features:f.array(uPw).min(1).max(6),story:f.string()}),pPw=f.object({name:f.string(),availability:y$2,order:f.number(),slug:f.string()}),g$2=C$2.extend({entityType:f.literal("product"),metadata:pPw,frontmatter:cPw,body:lPw,labels:f.record(f.string(),f.string()),url:f.string().optional(),typeLabel:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),ogImageUrl:f.string().optional()}),IH0=f.object({title:f.string(),description:f.string()}),iPw=f.object({heading:f.string(),buttonText:f.string(),link:f.string()}),dPw=f.object({headline:f.string(),tagline:f.string()}),nPw=f.object({vision:f.string(),pillars:f.array(IH0).min(1).max(6),approach:f.array(IH0).min(1).max(6),productsIntro:f.string(),technologies:f.array(IH0).min(1).max(6),benefits:f.array(IH0).min(1).max(6),cta:iPw}),rPw=f.object({headline:f.string(),slug:f.string()}),oPw=C$2.extend({entityType:f.literal("products-overview"),metadata:rPw,frontmatter:dPw,body:nPw,labels:f.record(f.string(),f.string())}),sPw=f.object({overview:oPw,products:f.array(g$2)}),aPw=f.object({product:g$2});class te0 extends fw{entityType=qH0.entityType;schema=cE;adapter=qH0;unregisterPrintableAttachmentProvider;unregisterOgImageAttachmentProvider;constructor(A={}){super("products",h$2,A,oe0)}getTemplates(){return{"product-list":s1({name:"product-list",description:"Products page \u2014 overview + brain model cards",schema:sPw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:P$2}}),"product-detail":s1({name:"product-detail",description:"Individual product detail page",schema:aPw,dataSourceId:"products:entities",requiredPermission:"public",layout:{component:M$2}})}}getDataSources(){return[new VH0(this.logger.child("ProductsDataSource"))]}async onRegister(A){this.unregisterPrintableAttachmentProvider=A.attachments.register("product",JH0,new se0(A)),this.unregisterOgImageAttachmentProvider=A.attachments.register("product",FH0,new ae0(A)),A.entities.register("products-overview",pE,re0)}async onShutdown(){this.unregisterPrintableAttachmentProvider?.(),this.unregisterPrintableAttachmentProvider=void 0,this.unregisterOgImageAttachmentProvider?.(),this.unregisterOgImageAttachmentProvider=void 0}}function Aa(A={}){return new te0(A)}fA();C0();C0();var tPw=f.enum(["public","shared","restricted"]),E$2=f.object({includeEntityTypes:f.array(f.string()).default([]),minRelevanceScore:f.number().min(0).max(1).default(0.5),mergeSimilarityThreshold:f.number().min(0).max(1).default(0.85),autoMerge:f.boolean().default(!0),extractableStatuses:f.array(f.string()).default(["published"]),enableAutoExtraction:f.boolean().default(!0),extractionVisibility:tPw.default("public"),sourceChangeBatchDelayMs:f.number().int().min(0).default(1000)});fA();C0();fA();var lN8=f.object({}),ePw=f.record(f.string(),f.unknown()).transform(()=>({})),dE=TQ.extend({entityType:f.literal("topic"),metadata:ePw}),pN8=f.object({content:f.string()}),T$2=f.object({title:f.string().describe("Topic title")});var IM="topics",K$="topic",ee0="topics-projection",S$2="topic:project",bH0="topics-plugin",m$2="topics:batch-completed",u$2="topics-source-batch";class GG extends r2{constructor(){super({entityType:K$,purpose:"A recurring theme or subject derived from the user's content.",schema:dE,frontmatterSchema:T$2})}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:K$}}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))}}fA();C0();C0();var AMw=f.object({title:f.string().max(100),content:f.string(),relevanceScore:f.number().min(0).max(1)}),c$2=f.array(AMw);var QMw=f.object({topics:c$2}),l$2=s1({name:"topics:extraction",description:"Extract topics from conversation text",dataSourceId:"shell:ai-content",schema:QMw,basePrompt:`You are an expert at analyzing content and extracting key topics.
|
|
7865
7865
|
|
|
7866
7866
|
Analyze the provided content and extract meaningful topics discussed.
|
|
7867
7867
|
|
|
@@ -7964,13 +7964,13 @@ ${A.incomingTopic.content}`})}}function GMw(A){if(A.length===0)return"";return A
|
|
|
7964
7964
|
|
|
7965
7965
|
${Q.content}`}).join(`
|
|
7966
7966
|
|
|
7967
|
-
`)}async function bM(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",H=A82(A),W=new DG(Q.entityService,w),K=$.topicMergeSynthesizer??new X0A(Q,w),U=await jH0(Q.entityService,void 0,Z),G=new Map,q=0,V=0,J=0;for(let k of H){w.info(`Processing batch of ${k.length} entities`);let j=GMw(k),_=PH0({entityTitle:`Batch of ${k.length} entities`,entityType:"batch",content:j,existingTopicTitles:U});try{let R=(await Q.ai.generate({prompt:_,templateName:"topics:extraction"})).topics.filter((x)=>x.relevanceScore>=B);for(let x of R)try{if(X){let u=await W.findMergeCandidate({incoming:x,threshold:Y,additionalCandidates:Array.from(G.values()),targetVisibility:Z});if(u){let n=await K.synthesize({existingTopic:u.topic,incomingTopic:x}),e=await W.applySynthesizedMerge({existingId:u.topic.id,synthesized:{...n,title:u.title},visibility:Z});if(!e)throw Error(`Failed to merge topic: ${x.title}`);G.set(e.id,e),V++;continue}}let M=W.getTopicIdForTitle(x.title,Z);if(G.has(M)){J++;continue}let S=await W.createTopicOptimistic({title:x.title,content:x.content,visibility:Z});if(S.topic)G.set(S.topic.id,S.topic);if(S.created)q++;else J++}catch(M){w.error("Topic batch item failed",{title:x.title,error:dA(M)})}}catch(O){w.error("Batch topic extraction failed",{batchSize:k.length,promptChars:_.length,error:dA(O)})}}let F={created:q,merged:V,skipped:J,batches:H.length};if(q>0||V>0)await Q.messaging.send({type:m$2,payload:F,broadcast:!0});return F}fA();C0();var DMw=f.discriminatedUnion("mode",[f.object({mode:f.literal("derive"),reason:f.string().optional()}),f.object({mode:f.literal("rebuild"),reason:f.string().optional()}),f.object({mode:f.literal("source-batch"),minRelevanceScore:f.number().min(0).max(1).optional()})]);class Y0A{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 Y82(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 qMw({context:Q,logger:w,config:$,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:B.minRelevanceScore??$.minRelevanceScore})},validateAndParse:(B)=>{let X=DMw.safeParse(B??{});return X.success?X.data:null}}}async function qMw(A){let Q=A.sourceBatch.drain(),w=await Promise.all(Q.map(async(W)=>({ref:W,entity:await A.context.entityService.getEntity({entityType:W.entityType,id:W.entityId})}))),$=0,B=0,X=0,Y=0,Z=[];for(let{ref:W,entity:K}of w){if(!K){B++;continue}if(K.contentHash!==W.contentHash){$++;continue}if(!A.isEntityPublished(K)){X++;continue}if(!xF(K.visibility,A.config.extractionVisibility)){Y++;continue}Z.push(K)}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 H=await bM(Z,A.context,A.logger,{minRelevanceScore:A.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});return{success:!0,sources:Q.length,...H,stale:$,missing:B,unpublished:X,hidden:Y}}function Z82(){return{priority:5,source:bH0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:IM}}}async function f82(A){let Q=await W82(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 bM(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 H82(A){let Q=await W82(A),w=await Z0A(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",w)}async function Z0A(A,Q,w,$){let B=new DG(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 bM(A,Q,w,{minRelevanceScore:$.minRelevanceScore,autoMerge:$.autoMerge,mergeSimilarityThreshold:$.mergeSimilarityThreshold,targetVisibility:$.extractionVisibility});return{deleted:X.length,...Y}}async function W82(A){let Q=zMw(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 zMw(A){return A.context.entityService.getEntityTypes().filter((w)=>A.shouldProcessEntityType(w))}var oE=f.object({entityType:f.string(),content:f.string(),metadata:f.record(f.string(),f.unknown()).optional()}),VMw=oE.extend({minRelevanceScore:f.number().optional()}),JMw=f.object({contentA:oE,contentB:oE,minRelevanceScore:f.number().optional(),threshold:f.number().min(0).max(1).optional()}),Ba=f.object({title:f.string(),content:f.string()}),FMw=f.object({existingTopics:f.array(Ba),incomingTopic:Ba,threshold:f.number().optional()}),IMw=f.object({existingTopics:f.array(Ba).default([]),incomingTopic:Ba.extend({relevanceScore:f.number().min(0).max(1).optional()}),threshold:f.number().optional()}),bMw=f.object({entities:f.array(oE).min(1),minRelevanceScore:f.number().optional()}),LMw=f.object({existingTopics:f.array(Ba).optional(),entities:f.array(oE)}),kMw=f.object({entities:f.array(oE)});function rE(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:b6(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function K82(A){return{title:A.title,relevanceScore:A.relevanceScore}}function _Mw(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function NMw(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:_Mw(Q)}]}}async function LM(A){let Q=await A.entityService.listEntities({entityType:K$});await Promise.all(Q.map((w)=>A.entityService.deleteEntity({entityType:K$,id:w.id})))}async function jMw(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise((w)=>setTimeout(w,100))}}function U82(A){let{context:Q,logger:w,config:$}=A,B=new B0A(Q,w),X=async(Y,Z,H="")=>{let W=rE(Y,H);return B.extractFromEntity(W,Z)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await LM(Q);let Z=VMw.parse(Y),H=Z.minRelevanceScore??$.minRelevanceScore,W=rE(Z);return(await B.extractFromEntity(W,H)).map((U)=>NMw(U,W))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await LM(Q);let Z=JMw.parse(Y),H=Z.minRelevanceScore??$.minRelevanceScore,W=Z.threshold??$.mergeSimilarityThreshold,[K,U]=await Promise.all([X(Z.contentA,H,"-a"),X(Z.contentB,H,"-b")]),G=new DG(Q.entityService,w),q=[];for(let F of K){let k=await G.createTopic(F);if(k)q.push(k)}let V=(await Promise.all(U.map(async(F)=>{let k=await G.findMergeCandidate({incoming:F,threshold:W,additionalCandidates:q});if(!k)return null;return{incomingTitle:F.title,candidateTitle:k.title,candidateScore:k.score}}))).filter((F)=>F!==null),J=V.map((F)=>F.candidateTitle);return{topicsA:K.map(K82),topicsB:U.map(K82),matchingTitles:J,mergeCandidates:V,wouldMerge:V.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await LM(Q);let Z=FMw.parse(Y),H=Z.threshold??$.mergeSimilarityThreshold,W=new DG(Q.entityService,w),K=[];for(let G of Z.existingTopics){let q=await W.createTopic(G);if(q)K.push(q)}let U=await W.findMergeCandidate({incoming:{title:Z.incomingTopic.title},threshold:H,additionalCandidates:K});return{found:U!==null,candidateTitle:U?.title,candidateScore:U?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(Y)=>{await LM(Q);let Z=IMw.parse(Y),H=new DG(Q.entityService,w);for(let G of Z.existingTopics)await H.createTopic({title:G.title,content:G.content});await jMw(Q);let W=rE({entityType:"post",content:Z.incomingTopic.content,metadata:{title:Z.incomingTopic.title}},"-source"),K=await bM([W],Q,w,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:Z.threshold??$.mergeSimilarityThreshold}),U=await Q.entityService.listEntities({entityType:K$});return{...K,topicCount:U.length,topics:U.map(w0A)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await LM(Q);let Z=LMw.parse(Y),H=new DG(Q.entityService,w);for(let G of Z.existingTopics??[])await H.createTopic(G);let W=Z.entities.map((G,q)=>rE(G,`-rebuild-${q}`)),K=await Z0A(W,Q,w,$),U=await Q.entityService.listEntities({entityType:K$});return{...K,topicCount:U.length,topics:U.map(w0A)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await LM(Q);let Z=bMw.parse(Y),H=Z.minRelevanceScore??$.minRelevanceScore,W=new DG(Q.entityService,w),K=[];for(let[G,q]of Z.entities.entries()){let V=rE(q,`-sequential-${G}`),J=await B.extractFromEntity(V,H);for(let F of J)await W.createTopic({title:F.title,content:F.content});K.push({extractedTitles:J.map((F)=>F.title)})}let U=await Q.entityService.listEntities({entityType:K$});return{totalTopics:U.length,perEntity:K,topics:U.map(nE)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await LM(Q);let H=kMw.parse(Y).entities.map((U,G)=>rE(U,`-batch-${G}`)),W=await bM(H,Q,w,{minRelevanceScore:$.minRelevanceScore}),K=await Q.entityService.listEntities({entityType:K$});return{...W,topics:K.map(nE)}})}var PMw=new GG;async function G82({entity:A,config:Q}){let w=dE.parse(A),$=PMw.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 f0A(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:m6["ai.rizom.brain.topic"],validate:!1,buildRecord:G82}}var D82={name:"@brains/topics",version:"0.2.0-alpha.168",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 OMw=new GG,xMw=f.looseObject({status:f.unknown().optional()});class q82 extends fw{entityType=K$;schema=dE;adapter=OMw;unregisterAtprotoProjection;sourceBatch=new Y0A;constructor(A={}){super(IM,D82,A,E$2)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:l$2,"merge-synthesis":p$2,"topic-list":i$2,"topic-detail":d$2}}getDataSources(){return[new $0A(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:ee0,targetType:K$,job:{type:S$2,handler:Y82({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 M_(A,K$,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:Z82()},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(!xF(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:bH0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:u$2,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:IM}})}}]}async onRegister(A){A.insights.register("topic-distribution",o$2()),s$2({context:A,pluginId:this.id}),U82({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=NB.getInstance().register(f0A())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(ee0)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===K$)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=xMw.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 f82({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await H82({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function MH0(A={}){return new q82(A)}fA();C0();fA();var H0A=f.enum(["linkedin"]),z82=f.enum(["linkedin"]),W0A=f.enum(["generating","draft","queued","published","failed"]),V82=f.enum(["generating","draft","queued","published","failed"]),J82=f.enum(["post","deck"]),RMw=f.enum(["post","deck"]),F82=f.object({id:f.string().min(1).describe("Document entity ID")}),vMw=f.object({id:f.string().min(1)}),qG=f.object({title:f.string().describe("Short descriptive title (3-6 words) for file naming"),platform:H0A.describe("Target platform"),status:W0A,coverImageId:f.string().optional().describe("Image entity ID for post image"),documents:f.array(F82).optional().describe("Document attachments for publishing"),publishedAt:f.string().datetime().optional(),platformPostId:f.string().optional().describe("ID from platform after publishing"),sourceEntityId:f.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:J82.optional().describe("Source entity type (post, deck)")}),I82=qG.extend({platform:H0A.optional(),status:W0A.optional()}),hMw=qG.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:f.string().describe("URL-friendly identifier: {platform}-{title}"),error:f.string().optional()}),CMw=f.object({title:f.string(),platform:z82,status:V82,publishedAt:f.string().datetime().optional(),platformPostId:f.string().optional(),slug:f.string(),error:f.string().optional()}),yMw=f.object({title:f.string(),platform:z82,status:V82,coverImageId:f.string().optional(),documents:f.array(vMw).optional(),publishedAt:f.string().datetime().optional(),platformPostId:f.string().optional(),sourceEntityId:f.string().optional(),sourceEntityType:RMw.optional()}),hL=TQ.extend({entityType:f.literal("social-post"),metadata:CMw}),OH0=hL.extend({frontmatter:yMw,body:f.string()}),gMw=OH0.extend({url:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),typeLabel:f.string().optional(),coverImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()});fA();k2();class K0A extends r2{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:hL,frontmatterSchema:qG,supportsCoverImage:!0})}toMarkdown(A){let Q,w={};try{w=this.parseFrontMatter(A.content,qG),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,I82),w=Q.platform??"linkedin",$=Q.status??"draft",B=`${w}-${q1(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,qG)}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-${q1(A.title)}`,platform:"linkedin",status:"generating"}}}}var V4=new K0A;fA();fA();C0();var EMw=f.looseObject({id:f.string().optional(),limit:f.number().optional(),page:f.number().optional(),pageSize:f.number().optional(),baseUrl:f.string().optional(),platform:f.enum(["linkedin"]).optional(),status:f.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:f.boolean().optional(),nextInQueue:f.boolean().optional()}),TMw=f.looseObject({entityType:f.string().optional(),query:EMw.optional()});function b82(A){let Q=BQ(A.content,qG);return OH0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class xH0 extends i5{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=TMw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return b82(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:K}=await this.fetchDetail($.id,B);return Q.parse(this.buildDetailResult(K,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:H,pagination:W}=await this.fetchList($,B,{...Y&&{filter:{metadata:X}},sortFields:Z});return Q.parse(this.buildListResult(H,W,$))}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=$?b82($):null;return A.parse({post:B})}}C0();var L82=f.object({accessToken:f.string().optional(),refreshToken:f.string().optional(),organizationId:f.string().optional(),apiVersion:f.string().regex(/^\d{6}$/).optional()}),U0A=f.object({linkedin:L82.optional(),publishInterval:f.number().default(3600000),enabled:f.boolean().default(!0),defaultPrompt:f.string().default("Create an engaging social media post that drives engagement"),maxRetries:f.number().default(3),autoGenerateOnBlogPublish:f.boolean().default(!1)});fA();k2();C0();Q$();D0A();import{jsxDEV as _5,Fragment as uMw}from"preact/jsx-dev-runtime";function SMw(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function mMw(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var vH0=({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 _5(uMw,{children:[_5(Bw,{title:B,description:Y},void 0,!1,void 0,this),_5("div",{className:"social-post-list bg-theme",children:_5("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[_5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:B},void 0,!1,void 0,this),A.length===0?_5("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):_5("ul",{className:"space-y-6",children:A.map((Z)=>_5("li",{children:_5(R6,{href:Z.url,variant:"horizontal",children:_5("div",{className:"flex flex-col sm:flex-row gap-4",children:[Z.coverImageUrl&&_5("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),_5("div",{className:"flex-1 min-w-0",children:[_5("div",{className:"flex items-start justify-between gap-4 mb-2",children:[_5("h2",{className:"text-lg font-semibold text-heading",children:Z.frontmatter.title},void 0,!1,void 0,this),_5("time",{className:"text-sm text-theme-muted shrink-0",children:mMw(Z.frontmatter.publishedAt??Z.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_5("div",{className:"flex items-center gap-2 mb-3",children:[_5(LZ,{status:Z.frontmatter.status},void 0,!1,void 0,this),_5("span",{className:"text-xs text-theme-muted uppercase",children:Z.frontmatter.platform},void 0,!1,void 0,this),_5("span",{className:"text-xs text-theme-muted font-mono",children:Z.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_5("p",{className:"text-theme leading-relaxed",children:SMw(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&&_5(mV,{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 N5,Fragment as cMw}from"preact/jsx-dev-runtime";function k82(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var hH0=({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 N5(cMw,{children:[N5(Bw,{title:Q,description:w},void 0,!1,void 0,this),N5("section",{className:"social-post-detail",children:N5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:N5("div",{className:"max-w-3xl mx-auto",children:[N5(Iq,{items:$},void 0,!1,void 0,this),N5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),N5("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[N5(LZ,{status:A.frontmatter.status},void 0,!1,void 0,this),N5("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),N5("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&&N5(TV,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),N5(R6,{className:"p-8 mb-8",children:N5("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),N5("div",{className:"space-y-4 text-sm text-theme-muted",children:[N5("div",{children:[N5("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",k82(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&N5("div",{children:[N5("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",k82(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&N5("div",{children:N5("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 Xa(A){return`social-media:${A}`}var lMw=f.union([f.boolean(),f.object({generate:f.boolean().optional(),prompt:f.string().optional()})]),q0A=f.object({prompt:f.string().optional(),platform:f.enum(["linkedin"]).optional(),sourceEntityType:f.enum(["post","deck"]).optional(),sourceEntityId:f.string().optional(),title:f.string().optional().describe("Required when content is provided directly"),content:f.string().optional(),addToQueue:f.boolean().optional(),generateImage:f.boolean().optional().describe("Auto-generate cover image for post"),coverImage:lMw.optional().describe("Generic cover image generation request")}),pMw=wf.extend({slug:f.string().optional()});class kM extends l4{constructor(A,Q){super(A,Q,{schema:q0A,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:H}=A;if(Z&&H)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(Z&&!H){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let F=await this.context.ai.generate({prompt:Z,templateName:Xa(w)});H=F.title,Z=F.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&X){await this.reportProgress(Q,{progress:10,message:`Fetching source ${X}`});let F=await this.context.entityService.getEntity({entityType:X,id:Y});if(!F)this.failEarly(`Source entity not found: ${X}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let j=f.looseObject({slug:f.string()}).safeParse(F.metadata),_=j.success?j.data.slug:Y,O=await this.context.ai.generate({prompt:`Create an engaging ${w} post to promote this ${X}:
|
|
7967
|
+
`)}async function bM(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",H=A82(A),W=new DG(Q.entityService,w),K=$.topicMergeSynthesizer??new X0A(Q,w),U=await jH0(Q.entityService,void 0,Z),G=new Map,q=0,V=0,J=0;for(let k of H){w.info(`Processing batch of ${k.length} entities`);let j=GMw(k),_=PH0({entityTitle:`Batch of ${k.length} entities`,entityType:"batch",content:j,existingTopicTitles:U});try{let R=(await Q.ai.generate({prompt:_,templateName:"topics:extraction"})).topics.filter((x)=>x.relevanceScore>=B);for(let x of R)try{if(X){let u=await W.findMergeCandidate({incoming:x,threshold:Y,additionalCandidates:Array.from(G.values()),targetVisibility:Z});if(u){let n=await K.synthesize({existingTopic:u.topic,incomingTopic:x}),e=await W.applySynthesizedMerge({existingId:u.topic.id,synthesized:{...n,title:u.title},visibility:Z});if(!e)throw Error(`Failed to merge topic: ${x.title}`);G.set(e.id,e),V++;continue}}let M=W.getTopicIdForTitle(x.title,Z);if(G.has(M)){J++;continue}let S=await W.createTopicOptimistic({title:x.title,content:x.content,visibility:Z});if(S.topic)G.set(S.topic.id,S.topic);if(S.created)q++;else J++}catch(M){w.error("Topic batch item failed",{title:x.title,error:dA(M)})}}catch(O){w.error("Batch topic extraction failed",{batchSize:k.length,promptChars:_.length,error:dA(O)})}}let F={created:q,merged:V,skipped:J,batches:H.length};if(q>0||V>0)await Q.messaging.send({type:m$2,payload:F,broadcast:!0});return F}fA();C0();var DMw=f.discriminatedUnion("mode",[f.object({mode:f.literal("derive"),reason:f.string().optional()}),f.object({mode:f.literal("rebuild"),reason:f.string().optional()}),f.object({mode:f.literal("source-batch"),minRelevanceScore:f.number().min(0).max(1).optional()})]);class Y0A{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 Y82(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 qMw({context:Q,logger:w,config:$,sourceBatch:A.sourceBatch,isEntityPublished:A.isEntityPublished,minRelevanceScore:B.minRelevanceScore??$.minRelevanceScore})},validateAndParse:(B)=>{let X=DMw.safeParse(B??{});return X.success?X.data:null}}}async function qMw(A){let Q=A.sourceBatch.drain(),w=await Promise.all(Q.map(async(W)=>({ref:W,entity:await A.context.entityService.getEntity({entityType:W.entityType,id:W.entityId})}))),$=0,B=0,X=0,Y=0,Z=[];for(let{ref:W,entity:K}of w){if(!K){B++;continue}if(K.contentHash!==W.contentHash){$++;continue}if(!A.isEntityPublished(K)){X++;continue}if(!xF(K.visibility,A.config.extractionVisibility)){Y++;continue}Z.push(K)}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 H=await bM(Z,A.context,A.logger,{minRelevanceScore:A.minRelevanceScore,autoMerge:A.config.autoMerge,mergeSimilarityThreshold:A.config.mergeSimilarityThreshold,targetVisibility:A.config.extractionVisibility});return{success:!0,sources:Q.length,...H,stale:$,missing:B,unpublished:X,hidden:Y}}function Z82(){return{priority:5,source:bH0,deduplication:"coalesce",deduplicationKey:"topics-initial-derivation",metadata:{operationType:"data_processing",operationTarget:"topics-initial-derivation",pluginId:IM}}}async function f82(A){let Q=await W82(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 bM(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 H82(A){let Q=await W82(A),w=await Z0A(Q,A.context,A.logger,A.config);A.logger.info("Topic rebuild complete",w)}async function Z0A(A,Q,w,$){let B=new DG(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 bM(A,Q,w,{minRelevanceScore:$.minRelevanceScore,autoMerge:$.autoMerge,mergeSimilarityThreshold:$.mergeSimilarityThreshold,targetVisibility:$.extractionVisibility});return{deleted:X.length,...Y}}async function W82(A){let Q=zMw(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 zMw(A){return A.context.entityService.getEntityTypes().filter((w)=>A.shouldProcessEntityType(w))}var oE=f.object({entityType:f.string(),content:f.string(),metadata:f.record(f.string(),f.unknown()).optional()}),VMw=oE.extend({minRelevanceScore:f.number().optional()}),JMw=f.object({contentA:oE,contentB:oE,minRelevanceScore:f.number().optional(),threshold:f.number().min(0).max(1).optional()}),Ba=f.object({title:f.string(),content:f.string()}),FMw=f.object({existingTopics:f.array(Ba),incomingTopic:Ba,threshold:f.number().optional()}),IMw=f.object({existingTopics:f.array(Ba).default([]),incomingTopic:Ba.extend({relevanceScore:f.number().min(0).max(1).optional()}),threshold:f.number().optional()}),bMw=f.object({entities:f.array(oE).min(1),minRelevanceScore:f.number().optional()}),LMw=f.object({existingTopics:f.array(Ba).optional(),entities:f.array(oE)}),kMw=f.object({entities:f.array(oE)});function rE(A,Q=""){return{id:`eval${Q}-${Date.now()}`,entityType:A.entityType,content:A.content,contentHash:b6(A.content),visibility:"public",metadata:A.metadata??{},created:new Date().toISOString(),updated:new Date().toISOString()}}function K82(A){return{title:A.title,relevanceScore:A.relevanceScore}}function _Mw(A){let Q=A.metadata.title;return typeof Q==="string"?Q:A.id}function NMw(A,Q){return{...A,sources:[{id:Q.id,type:Q.entityType,title:_Mw(Q)}]}}async function LM(A){let Q=await A.entityService.listEntities({entityType:K$});await Promise.all(Q.map((w)=>A.entityService.deleteEntity({entityType:K$,id:w.id})))}async function jMw(A){for(;;){if((await A.jobs.getActiveJobs(["shell:embedding"])).length===0)return;await new Promise((w)=>setTimeout(w,100))}}function U82(A){let{context:Q,logger:w,config:$}=A,B=new B0A(Q,w),X=async(Y,Z,H="")=>{let W=rE(Y,H);return B.extractFromEntity(W,Z)};Q.eval.registerHandler("extractFromEntity",async(Y)=>{await LM(Q);let Z=VMw.parse(Y),H=Z.minRelevanceScore??$.minRelevanceScore,W=rE(Z);return(await B.extractFromEntity(W,H)).map((U)=>NMw(U,W))}),Q.eval.registerHandler("checkMergeSimilarity",async(Y)=>{await LM(Q);let Z=JMw.parse(Y),H=Z.minRelevanceScore??$.minRelevanceScore,W=Z.threshold??$.mergeSimilarityThreshold,[K,U]=await Promise.all([X(Z.contentA,H,"-a"),X(Z.contentB,H,"-b")]),G=new DG(Q.entityService,w),q=[];for(let F of K){let k=await G.createTopic(F);if(k)q.push(k)}let V=(await Promise.all(U.map(async(F)=>{let k=await G.findMergeCandidate({incoming:F,threshold:W,additionalCandidates:q});if(!k)return null;return{incomingTitle:F.title,candidateTitle:k.title,candidateScore:k.score}}))).filter((F)=>F!==null),J=V.map((F)=>F.candidateTitle);return{topicsA:K.map(K82),topicsB:U.map(K82),matchingTitles:J,mergeCandidates:V,wouldMerge:V.length>0}}),Q.eval.registerHandler("detectMergeCandidate",async(Y)=>{await LM(Q);let Z=FMw.parse(Y),H=Z.threshold??$.mergeSimilarityThreshold,W=new DG(Q.entityService,w),K=[];for(let G of Z.existingTopics){let q=await W.createTopic(G);if(q)K.push(q)}let U=await W.findMergeCandidate({incoming:{title:Z.incomingTopic.title},threshold:H,additionalCandidates:K});return{found:U!==null,candidateTitle:U?.title,candidateScore:U?.score}}),Q.eval.registerHandler("processTopicWithAutoMerge",async(Y)=>{await LM(Q);let Z=IMw.parse(Y),H=new DG(Q.entityService,w);for(let G of Z.existingTopics)await H.createTopic({title:G.title,content:G.content});await jMw(Q);let W=rE({entityType:"post",content:Z.incomingTopic.content,metadata:{title:Z.incomingTopic.title}},"-source"),K=await bM([W],Q,w,{minRelevanceScore:0,autoMerge:!0,mergeSimilarityThreshold:Z.threshold??$.mergeSimilarityThreshold}),U=await Q.entityService.listEntities({entityType:K$});return{...K,topicCount:U.length,topics:U.map(w0A)}}),Q.eval.registerHandler("rebuildTopics",async(Y)=>{await LM(Q);let Z=LMw.parse(Y),H=new DG(Q.entityService,w);for(let G of Z.existingTopics??[])await H.createTopic(G);let W=Z.entities.map((G,q)=>rE(G,`-rebuild-${q}`)),K=await Z0A(W,Q,w,$),U=await Q.entityService.listEntities({entityType:K$});return{...K,topicCount:U.length,topics:U.map(w0A)}}),Q.eval.registerHandler("extractSequentially",async(Y)=>{await LM(Q);let Z=bMw.parse(Y),H=Z.minRelevanceScore??$.minRelevanceScore,W=new DG(Q.entityService,w),K=[];for(let[G,q]of Z.entities.entries()){let V=rE(q,`-sequential-${G}`),J=await B.extractFromEntity(V,H);for(let F of J)await W.createTopic({title:F.title,content:F.content});K.push({extractedTitles:J.map((F)=>F.title)})}let U=await Q.entityService.listEntities({entityType:K$});return{totalTopics:U.length,perEntity:K,topics:U.map(nE)}}),Q.eval.registerHandler("batchExtract",async(Y)=>{await LM(Q);let H=kMw.parse(Y).entities.map((U,G)=>rE(U,`-batch-${G}`)),W=await bM(H,Q,w,{minRelevanceScore:$.minRelevanceScore}),K=await Q.entityService.listEntities({entityType:K$});return{...W,topics:K.map(nE)}})}var PMw=new GG;async function G82({entity:A,config:Q}){let w=dE.parse(A),$=PMw.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 f0A(){return{entityType:"topic",collection:"ai.rizom.brain.topic",lexicon:m6["ai.rizom.brain.topic"],validate:!1,buildRecord:G82}}var D82={name:"@brains/topics",version:"0.2.0-alpha.169",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 OMw=new GG,xMw=f.looseObject({status:f.unknown().optional()});class q82 extends fw{entityType=K$;schema=dE;adapter=OMw;unregisterAtprotoProjection;sourceBatch=new Y0A;constructor(A={}){super(IM,D82,A,E$2)}getEntityTypeConfig(){return{weight:0.5,projectionSource:!1}}getTemplates(){return{extraction:l$2,"merge-synthesis":p$2,"topic-list":i$2,"topic-detail":d$2}}getDataSources(){return[new $0A(this.logger.child("TopicsDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableAutoExtraction)return[];return[{id:ee0,targetType:K$,job:{type:S$2,handler:Y82({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 M_(A,K$,{visibility:this.config.extractionVisibility}),jobData:{mode:"derive",reason:"initial-sync"},jobOptions:Z82()},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(!xF(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:bH0,delayMs:this.config.sourceChangeBatchDelayMs,deduplication:"skip",deduplicationKey:u$2,metadata:{operationType:"data_processing",operationTarget:"topic-source-batch",pluginId:IM}})}}]}async onRegister(A){A.insights.register("topic-distribution",o$2()),s$2({context:A,pluginId:this.id}),U82({context:A,logger:this.logger,config:this.config}),this.unregisterAtprotoProjection=NB.getInstance().register(f0A())}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}hasRunInitialDerivation(){return this.getDerivedEntityProjectionController(ee0)?.hasQueuedInitialSync()??!1}shouldProcessEntityType(A,Q){if(A===K$)return!1;if(!this.config.includeEntityTypes.includes(A))return!1;return Q.getEntityTypeConfig(A).projectionSource!==!1}isEntityPublished(A){let Q=xMw.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 f82({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}async rebuildAllTopics(A){await H82({context:A,logger:this.logger,config:this.config,shouldProcessEntityType:(Q)=>this.shouldProcessEntityType(Q,A.entityService),isEntityPublished:(Q)=>this.isEntityPublished(Q)})}}function MH0(A={}){return new q82(A)}fA();C0();fA();var H0A=f.enum(["linkedin"]),z82=f.enum(["linkedin"]),W0A=f.enum(["generating","draft","queued","published","failed"]),V82=f.enum(["generating","draft","queued","published","failed"]),J82=f.enum(["post","deck"]),RMw=f.enum(["post","deck"]),F82=f.object({id:f.string().min(1).describe("Document entity ID")}),vMw=f.object({id:f.string().min(1)}),qG=f.object({title:f.string().describe("Short descriptive title (3-6 words) for file naming"),platform:H0A.describe("Target platform"),status:W0A,coverImageId:f.string().optional().describe("Image entity ID for post image"),documents:f.array(F82).optional().describe("Document attachments for publishing"),publishedAt:f.string().datetime().optional(),platformPostId:f.string().optional().describe("ID from platform after publishing"),sourceEntityId:f.string().optional().describe("Source entity ID if auto-generated"),sourceEntityType:J82.optional().describe("Source entity type (post, deck)")}),I82=qG.extend({platform:H0A.optional(),status:W0A.optional()}),hMw=qG.pick({title:!0,platform:!0,status:!0,publishedAt:!0,platformPostId:!0}).extend({slug:f.string().describe("URL-friendly identifier: {platform}-{title}"),error:f.string().optional()}),CMw=f.object({title:f.string(),platform:z82,status:V82,publishedAt:f.string().datetime().optional(),platformPostId:f.string().optional(),slug:f.string(),error:f.string().optional()}),yMw=f.object({title:f.string(),platform:z82,status:V82,coverImageId:f.string().optional(),documents:f.array(vMw).optional(),publishedAt:f.string().datetime().optional(),platformPostId:f.string().optional(),sourceEntityId:f.string().optional(),sourceEntityType:RMw.optional()}),hL=TQ.extend({entityType:f.literal("social-post"),metadata:CMw}),OH0=hL.extend({frontmatter:yMw,body:f.string()}),gMw=OH0.extend({url:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),typeLabel:f.string().optional(),coverImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()});fA();k2();class K0A extends r2{constructor(){super({entityType:"social-post",purpose:"A short post drafted for social media such as LinkedIn or X.",schema:hL,frontmatterSchema:qG,supportsCoverImage:!0})}toMarkdown(A){let Q,w={};try{w=this.parseFrontMatter(A.content,qG),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,I82),w=Q.platform??"linkedin",$=Q.status??"draft",B=`${w}-${q1(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,qG)}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-${q1(A.title)}`,platform:"linkedin",status:"generating"}}}}var V4=new K0A;fA();fA();C0();var EMw=f.looseObject({id:f.string().optional(),limit:f.number().optional(),page:f.number().optional(),pageSize:f.number().optional(),baseUrl:f.string().optional(),platform:f.enum(["linkedin"]).optional(),status:f.enum(["generating","draft","queued","published","failed"]).optional(),sortByQueue:f.boolean().optional(),nextInQueue:f.boolean().optional()}),TMw=f.looseObject({entityType:f.string().optional(),query:EMw.optional()});function b82(A){let Q=BQ(A.content,qG);return OH0.parse({...A,frontmatter:Q.metadata,body:Q.content})}class xH0 extends i5{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=TMw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){return b82(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:K}=await this.fetchDetail($.id,B);return Q.parse(this.buildDetailResult(K,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:H,pagination:W}=await this.fetchList($,B,{...Y&&{filter:{metadata:X}},sortFields:Z});return Q.parse(this.buildListResult(H,W,$))}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=$?b82($):null;return A.parse({post:B})}}C0();var L82=f.object({accessToken:f.string().optional(),refreshToken:f.string().optional(),organizationId:f.string().optional(),apiVersion:f.string().regex(/^\d{6}$/).optional()}),U0A=f.object({linkedin:L82.optional(),publishInterval:f.number().default(3600000),enabled:f.boolean().default(!0),defaultPrompt:f.string().default("Create an engaging social media post that drives engagement"),maxRetries:f.number().default(3),autoGenerateOnBlogPublish:f.boolean().default(!1)});fA();k2();C0();Q$();D0A();import{jsxDEV as _5,Fragment as uMw}from"preact/jsx-dev-runtime";function SMw(A,Q){if(A.length<=Q)return A;return A.slice(0,Q).trim()+"..."}function mMw(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"short",day:"numeric"})}var vH0=({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 _5(uMw,{children:[_5(Bw,{title:B,description:Y},void 0,!1,void 0,this),_5("div",{className:"social-post-list bg-theme",children:_5("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[_5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:B},void 0,!1,void 0,this),A.length===0?_5("p",{className:"text-theme-muted italic",children:"No social posts yet."},void 0,!1,void 0,this):_5("ul",{className:"space-y-6",children:A.map((Z)=>_5("li",{children:_5(R6,{href:Z.url,variant:"horizontal",children:_5("div",{className:"flex flex-col sm:flex-row gap-4",children:[Z.coverImageUrl&&_5("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),_5("div",{className:"flex-1 min-w-0",children:[_5("div",{className:"flex items-start justify-between gap-4 mb-2",children:[_5("h2",{className:"text-lg font-semibold text-heading",children:Z.frontmatter.title},void 0,!1,void 0,this),_5("time",{className:"text-sm text-theme-muted shrink-0",children:mMw(Z.frontmatter.publishedAt??Z.created)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_5("div",{className:"flex items-center gap-2 mb-3",children:[_5(LZ,{status:Z.frontmatter.status},void 0,!1,void 0,this),_5("span",{className:"text-xs text-theme-muted uppercase",children:Z.frontmatter.platform},void 0,!1,void 0,this),_5("span",{className:"text-xs text-theme-muted font-mono",children:Z.id},void 0,!1,void 0,this)]},void 0,!0,void 0,this),_5("p",{className:"text-theme leading-relaxed",children:SMw(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&&_5(mV,{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 N5,Fragment as cMw}from"preact/jsx-dev-runtime";function k82(A){return new Date(A).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric",hour:"numeric",minute:"2-digit"})}var hH0=({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 N5(cMw,{children:[N5(Bw,{title:Q,description:w},void 0,!1,void 0,this),N5("section",{className:"social-post-detail",children:N5("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:N5("div",{className:"max-w-3xl mx-auto",children:[N5(Iq,{items:$},void 0,!1,void 0,this),N5("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-4",children:A.frontmatter.title},void 0,!1,void 0,this),N5("div",{className:"flex flex-wrap items-center gap-3 mb-6",children:[N5(LZ,{status:A.frontmatter.status},void 0,!1,void 0,this),N5("span",{className:"text-sm text-theme-muted uppercase",children:A.frontmatter.platform},void 0,!1,void 0,this),N5("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&&N5(TV,{src:A.coverImageUrl,alt:A.frontmatter.title,width:A.coverImageWidth,height:A.coverImageHeight,className:"mb-8"},void 0,!1,void 0,this),N5(R6,{className:"p-8 mb-8",children:N5("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),N5("div",{className:"space-y-4 text-sm text-theme-muted",children:[N5("div",{children:[N5("span",{className:"font-medium",children:"Created:"},void 0,!1,void 0,this)," ",k82(A.created)]},void 0,!0,void 0,this),A.frontmatter.publishedAt&&N5("div",{children:[N5("span",{className:"font-medium",children:"Published:"},void 0,!1,void 0,this)," ",k82(A.frontmatter.publishedAt)]},void 0,!0,void 0,this),A.frontmatter.platformPostId&&N5("div",{children:N5("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 Xa(A){return`social-media:${A}`}var lMw=f.union([f.boolean(),f.object({generate:f.boolean().optional(),prompt:f.string().optional()})]),q0A=f.object({prompt:f.string().optional(),platform:f.enum(["linkedin"]).optional(),sourceEntityType:f.enum(["post","deck"]).optional(),sourceEntityId:f.string().optional(),title:f.string().optional().describe("Required when content is provided directly"),content:f.string().optional(),addToQueue:f.boolean().optional(),generateImage:f.boolean().optional().describe("Auto-generate cover image for post"),coverImage:lMw.optional().describe("Generic cover image generation request")}),pMw=wf.extend({slug:f.string().optional()});class kM extends l4{constructor(A,Q){super(A,Q,{schema:q0A,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:H}=A;if(Z&&H)await this.reportProgress(Q,{progress:50,message:"Using provided content"});else if(Z&&!H){await this.reportProgress(Q,{progress:10,message:"Shaping content with AI"});let F=await this.context.ai.generate({prompt:Z,templateName:Xa(w)});H=F.title,Z=F.content,await this.reportProgress(Q,{progress:50,message:"Social post shaped from content"})}else if(Y&&X){await this.reportProgress(Q,{progress:10,message:`Fetching source ${X}`});let F=await this.context.entityService.getEntity({entityType:X,id:Y});if(!F)this.failEarly(`Source entity not found: ${X}/${Y}`);await this.reportProgress(Q,{progress:30,message:"Generating social post from source content"});let j=f.looseObject({slug:f.string()}).safeParse(F.metadata),_=j.success?j.data.slug:Y,O=await this.context.ai.generate({prompt:`Create an engaging ${w} post to promote this ${X}:
|
|
7968
7968
|
|
|
7969
7969
|
Source: ${X}/${_}
|
|
7970
7970
|
|
|
7971
7971
|
${F.content}`,templateName:Xa(w)});H=O.title,Z=O.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:Xa(w)});H=F.title,Z=F.content,await this.reportProgress(Q,{progress:50,message:"Social post generated"})}else this.failEarly("No content source provided (prompt, sourceEntityId, or content)");if(!Z||!H)this.failEarly("Content or title was not generated");let K={title:H,platform:w,status:$?"queued":"draft",...Y&&{sourceEntityId:Y},...X&&{sourceEntityType:X}},U=V4.createPostContent(K,Z),q=V4.fromMarkdown(U).metadata;if(!q)this.failEarly("Failed to parse social post metadata");let V=await tK({entityType:"social-post",title:H,deriveId:(F)=>`${w}-${q1(F)}`,regeneratePrompt:"Generate a different social media post title on the same topic.",context:this.context}),J=U;if(V!==H){q.title=V,q.slug=`${w}-${q1(V)}`;let F={...K,title:V};J=V4.createPostContent(F,Z)}return{id:q.slug,content:J,metadata:q,title:V,resultExtras:{slug:q.slug},createOptions:{deduplicateId:!0}}}async onGenerationFailure(A,Q){await this.context.messaging.send({type:"generate:report:failure",payload:{entityType:"social-post",error:Q}})}async afterCreate(A,Q,w,$){if(A.generateImage){await this.reportProgress(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}}}C0();var _82=200,N82="com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest";function Ya(A){if(A.length<=_82)return A;return`${A.slice(0,_82)}\u2026 (truncated, ${A.length} bytes)`}var iMw=f.looseObject({sub:f.string()}),dMw=f.looseObject({id:f.string()}),nMw=f.looseObject({value:f.looseObject({asset:f.string(),uploadMechanism:f.looseObject({[N82]:f.looseObject({uploadUrl:f.url()})})})}).transform((A)=>({uploadUrl:A.value.uploadMechanism[N82].uploadUrl,assetUrn:A.value.asset})),rMw=f.looseObject({value:f.looseObject({uploadUrl:f.url(),document:f.string()})}).transform((A)=>({uploadUrl:A.value.uploadUrl,documentUrn:A.value.document}));function oMw(A){let Q={status:"READY",media:A.urn};if(A.title)Q.title={text:A.title};return Q}function sMw(A){let Q=nMw.safeParse(A);return Q.success?Q.data:null}function aMw(A){let Q=rMw.safeParse(A);return Q.success?Q.data:null}var tMw="202604";class z0A{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 U=await this.uploadDocument(B,X);return this.publishDocumentPost(B,A,U,X.filename)}else if(w){let U=await this.uploadImage(B,w);if(U)Y={category:"IMAGE",urn:U}}let Z={shareCommentary:{text:A},shareMediaCategory:Y?.category??"NONE",...Y&&{media:[oMw(Y)]}},H=await this.fetch(`${this.apiBaseUrl}/ugcPosts`,{method:"POST",headers:{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","X-Restli-Protocol-Version":"2.0.0"},body:JSON.stringify({author:B,lifecycleState:"PUBLISHED",specificContent:{"com.linkedin.ugc.ShareContent":Z},visibility:{"com.linkedin.ugc.MemberNetworkVisibility":"PUBLIC"}})});if(!H.ok){let U=Ya(await H.text());throw this.logger.error("LinkedIn API error",{status:H.status,error:U}),Error(`LinkedIn API error: ${H.status} - ${U}`)}let W=H.headers.get("X-RestLi-Id")??"";this.logger.info("LinkedIn post created",{postId:W,mediaCategory:Y?.category??"NONE"});let K={id:W};if(W)K.url=`https://www.linkedin.com/feed/update/${W}`;return K}getRestHeaders(){return{Authorization:`Bearer ${this.config.accessToken}`,"Content-Type":"application/json","Linkedin-Version":this.config.apiVersion??tMw,"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=Ya(await w.text());return this.logger.warn("LinkedIn image upload registration failed",{status:w.status,error:Z}),null}let $=sMw(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=Ya(await w.text());throw Error(`LinkedIn document upload initialization failed: ${w.status} - ${X}`)}let $=aMw(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=Ya(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 $=iMw.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=Ya(await A.text());throw Error(`Failed to get LinkedIn user ID: ${A.status} - ${w}`)}let Q=dMw.parse(await A.json());return this.cachedUserId=`urn:li:person:${Q.id}`,this.cachedUserId}}function V0A(A,Q,w={}){return new z0A(A,Q,w)}C0();n$();D0A();var eMw=f.object({currentPage:f.number(),totalPages:f.number(),totalItems:f.number(),pageSize:f.number(),hasNextPage:f.boolean(),hasPrevPage:f.boolean()}),AOw=f.union([f.enum(["public","shared","restricted"]),f.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),j82=f.enum(["linkedin"]),P82=f.enum(["generating","draft","queued","published","failed"]),QOw=f.enum(["post","deck"]),wOw=f.object({id:f.string().min(1)}),$Ow=f.object({title:f.string(),platform:j82,status:P82,coverImageId:f.string().optional(),documents:f.array(wOw).optional(),publishedAt:f.string().optional(),platformPostId:f.string().optional(),sourceEntityId:f.string().optional(),sourceEntityType:QOw.optional()}),BOw=f.object({title:f.string(),platform:j82,status:P82,publishedAt:f.string().optional(),platformPostId:f.string().optional(),slug:f.string(),error:f.string().optional()}),M82=f.object({id:f.string(),entityType:f.literal("social-post"),content:f.string(),created:f.string(),updated:f.string(),visibility:AOw,metadata:BOw,contentHash:f.string(),frontmatter:$Ow,body:f.string(),url:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),typeLabel:f.string().optional(),coverImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()}),XOw=f.object({posts:f.array(M82),totalCount:f.number().optional(),pagination:eMw.nullable(),baseUrl:f.string().optional()}),YOw=f.object({post:M82});function O82(){return{linkedin:RH0,"social-post-list":s1({name:"social-post-list",description:"Social post list page template",schema:XOw,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:vH0}}),"social-post-detail":s1({name:"social-post-detail",description:"Individual social post template",schema:YOw,dataSourceId:"social-media:posts",requiredPermission:"public",layout:{component:hH0}})}}C0();var ZOw=f.object({prompt:f.string().optional(),content:f.string().optional(),platform:f.enum(["linkedin"]).default("linkedin")}),fOw=f.object({prompt:f.string().optional(),content:f.string().optional(),title:f.string().optional(),platform:f.enum(["linkedin"]).optional()});function x82(A){A.eval.registerHandler("generation",async(Q)=>{let w=ZOw.parse(Q),$=w.content?`Create an engaging LinkedIn post to share this content:
|
|
7972
7972
|
|
|
7973
|
-
${w.content}`:w.prompt??"Write an engaging LinkedIn post";return A.ai.generate({prompt:$,templateName:`social-media:${w.platform}`})}),A.eval.registerHandler("create",async(Q)=>{let w=fOw.parse(Q),$=[],B=gX.from(async(W)=>{let K={progress:W.progress};if(W.message!==void 0)K.message=W.message;$.push(K)});if(!B)throw Error("Failed to create progress reporter");let Y=await new kM(A.logger,A).process(w,`eval-${Date.now()}`,B),Z=!1,H;if(Y.success&&Y.entityId){let W=await A.entityService.getEntity({entityType:"social-post",id:Y.entityId});Z=!!W,H=W?.content.slice(0,300)}return{...Y,entityExists:Z,entityPreview:H,progressSteps:$}})}fA();class Za{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=BQ(B.content,qG),H;if(Z.metadata.coverImageId)H=await this.fetchImageData(Z.metadata.coverImageId);let W=Z.metadata.documents??[],K=await this.fetchDocumentData(W);try{if(W.length>0&&K.length===0)throw Error(`Refusing to publish: ${W.length} document(s) referenced but none could be fetched`);let U=W.length===0?await this.resolveSourceAttachment(Z.metadata):[],G=K.length>0?K:U,q=G.length?await Y.publish(Z.content,B.metadata,H,G):await Y.publish(Z.content,B.metadata,H),V=new Date().toISOString(),J=q.id||void 0,F={...Z.metadata,status:"published",publishedAt:V,...J&&{platformPostId:J}},k=V4.createPostContent(F,Z.content);await this.entityService.updateEntity({entity:{...B,content:k,metadata:{...B.metadata,status:"published",publishedAt:V,platformPostId:J}}}),await this.reportSuccess(Q,w,q.id),this.logger.info(`Post published successfully: ${w}`,{platform:X,platformPostId:J})}catch(U){let G=U instanceof Error?U.message:String(U),q={...Z.metadata,status:"failed"},V=V4.createPostContent(q,Z.content);await this.entityService.updateEntity({entity:{...B,content:V,metadata:{...B.metadata,status:"failed"}}}),await this.reportFailure(Q,w,G),this.logger.error(`Post publish failed: ${w}`,{platform:X,error:G})}}catch($){let B=dA($);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 R82(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 v82(A,Q,w){let $=new Za({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 h82(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 H=dA(Z);return Q.error(`Failed to trigger auto-generate for ${B}:`,{error:H}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function C82(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:`${V4.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=dA(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 y82(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:`${V4.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=dA(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 g82({entity:A,config:Q}){let w=hL.parse(A),$=V4.parsePostFrontmatter(w),B=V4.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 J0A(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:m6["ai.rizom.brain.socialPost"],validate:!1,buildRecord:g82}}var E82={name:"@brains/social-media",version:"0.2.0-alpha.168",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 F0A extends fw{entityType=V4.entityType;schema=hL;adapter=V4;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",E82,A,U0A)}createGenerationHandler(A){return new kM(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return O82()}getDataSources(){return[new xH0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),R82(A,this.providers,this.logger),v82(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)h82(A,this.logger),C82(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");y82(A,this.logger),x82(A),this.unregisterAtprotoProjection=NB.getInstance().register(J0A()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=V0A(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function fa(A={}){return new F0A(A)}C0();var WOw=f.enum(["draft","queued","published","failed"]),T82=f.object({status:WOw.default("draft"),queueOrder:f.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:f.string().datetime().optional()});class I0A{name="internal";async publish(A,Q){return{id:"internal"}}}var Ha={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},_Y={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"},CL={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"},S82={REGISTER:"publish-assets:register"};C0();var KOw=f.enum(["provider"]),m82=f.object({executionMode:KOw.optional(),publishResultIdField:f.string().min(1).optional(),publishTimestampField:f.string().min(1).optional(),enabled:f.boolean().optional()}).strict();var UOw=f.object({skipIfDraftExists:f.boolean().optional(),minSourceEntities:f.number().optional(),maxUnpublishedDrafts:f.number().optional(),sourceEntityType:f.string().optional()}),u82=f.object({entitySchedules:f.record(f.string(),f.string()).optional(),generationSchedules:f.record(f.string(),f.string()).optional(),generationConditions:f.record(f.string(),UOw).optional()});class lq{static instance=null;queues=new Map;static getInstance(){return lq.instance??=new lq,lq.instance}static resetInstance(){lq.instance=null}static createFresh(){return new lq}constructor(){}async add(A,Q,w=Ha){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}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 pq{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new I0A;static getInstance(){return pq.instance??=new pq,pq.instance}static resetInstance(){pq.instance=null}static createFresh(){return new pq}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 c82(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await GOw(A,Q)}async function GOw(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:_Y.FAILED,payload:$,sender:"publish-service",broadcast:!0});Q.onFailed?.($);return}b0A(A.entityType,A.entityId,w.result,Q)}catch(w){let $=dA(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 b0A(A,Q,w,$){if($.retryTracker.clearRetries(Q),$.messageBus)$.messageBus.send({type:_Y.COMPLETED,payload:{entityType:A,entityId:Q,result:w},sender:"publish-service",broadcast:!0});$.onPublish?.({entityType:A,entityId:Q,result:w})}function l82(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:_Y.FAILED,payload:X,sender:"publish-service",broadcast:!0});$.onFailed?.(X)}async function p82(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:CL.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:CL.EXECUTE,payload:$,sender:"content-pipeline"});Q.onGenerate?.($)}function i82(A,Q,w){if(w)w.send({type:CL.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function d82(A,Q,w){if(w)w.send({type:CL.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var DOw=1000;class L0A{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(DOw,()=>this.processUnscheduledTypes())}stop(){if(qOw(this.publishJobs),this.immediateIntervalJob)this.immediateIntervalJob.stop(),this.immediateIntervalJob=null}async processEntityType(A){if(!this.deps.isRunning())return;try{let Q=await this.deps.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.deps.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.deps.isRunning())return;try{let A=await this.deps.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let w=await this.deps.config.queueManager.getNext(Q);if(w){await this.processEntry(w);break}}}catch(A){this.deps.config.logger.error("Scheduler error for unscheduled types:",A)}}async processEntry(A){await this.deps.config.queueManager.remove(A.entityType,A.entityId);let Q=this.deps.getPublishDeps();await c82(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}function qOw(A){for(let Q of A.values())Q.stop();A.clear()}class k0A{deps;generationJobs=new Map;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.generationSchedules)){let w=this.deps.config.backend.scheduleCron(Q,()=>this.handleTriggerGeneration(A));this.generationJobs.set(A,w)}}stop(){zOw(this.generationJobs)}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await p82(A,this.deps.getGenerationDeps())}catch(Q){this.deps.config.logger.error(`Generation trigger error for ${A}:`,Q)}}get generationSchedules(){return this.deps.config.generationSchedules}}function zOw(A){for(let Q of A.values())Q.stop();A.clear()}class zG{static instance=null;config;publishRunner;generationRunner;running=!1;static getInstance(A){return zG.instance??=new zG(A),zG.instance}static resetInstance(){if(zG.instance)zG.instance.stop();zG.instance=null}static createFresh(A){return new zG(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new L0A({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new k0A({config:this.config,getGenerationDeps:()=>this.generationDeps,isRunning:()=>this.running})}async start(){if(this.running)return;this.running=!0,this.publishRunner.start(),this.generationRunner.start()}async stop(){this.running=!1,this.publishRunner.stop(),this.generationRunner.stop()}isRunning(){return this.running}completePublish(A,Q,w){b0A(A,Q,w,this.publishDeps)}failPublish(A,Q,w){l82(A,Q,w,this.publishDeps)}completeGeneration(A,Q){i82(A,Q,this.config.messageBus)}failGeneration(A,Q){d82(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}" - ${dA($)}`,{cause:$})}}}class iq{static instance=null;retries=new Map;static getInstance(){return iq.instance??=new iq,iq.instance}static resetInstance(){iq.instance=null}static createFresh(){return new iq}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}}}function Wa(A){return Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)}function _0A(A,Q){return A.y===Q.y&&A.m===Q.m&&A.d===Q.d&&A.h===Q.h&&A.i===Q.i&&A.s===Q.s}function VOw(A,Q){let w=new Date(Date.parse(A));if(isNaN(w))throw Error("Invalid ISO8601 passed to timezone parser.");let $=A.substring(9);return $.includes("Z")||$.includes("+")||$.includes("-")?j0A(w.getUTCFullYear(),w.getUTCMonth()+1,w.getUTCDate(),w.getUTCHours(),w.getUTCMinutes(),w.getUTCSeconds(),"Etc/UTC"):j0A(w.getFullYear(),w.getMonth()+1,w.getDate(),w.getHours(),w.getMinutes(),w.getSeconds(),Q)}function n82(A,Q,w){return s82(VOw(A,Q),w)}function s82(A,Q){let w=new Date(Wa(A)),$=Ka(w,A.tz),B=Wa(A),X=Wa($),Y=B-X,Z=new Date(w.getTime()+Y),H=Ka(Z,A.tz);if(_0A(H,A)){let U=new Date(Z.getTime()-3600000),G=Ka(U,A.tz);return _0A(G,A)?U:Z}let W=new Date(Z.getTime()+Wa(A)-Wa(H)),K=Ka(W,A.tz);if(_0A(K,A))return W;if(Q)throw Error("Invalid date passed to fromTZ()");return Z.getTime()>W.getTime()?Z:W}function Ka(A,Q){let w,$;try{w=new Intl.DateTimeFormat("en-US",{timeZone:Q,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric",hour12:!1}),$=w.formatToParts(A)}catch(X){let Y=X instanceof Error?X.message:String(X);throw RangeError(`toTZ: Invalid timezone '${Q}' or date. Please provide a valid IANA timezone (e.g., 'America/New_York', 'Europe/Stockholm'). Original error: ${Y}`)}let B={year:0,month:0,day:0,hour:0,minute:0,second:0};for(let X of $)(X.type==="year"||X.type==="month"||X.type==="day"||X.type==="hour"||X.type==="minute"||X.type==="second")&&(B[X.type]=parseInt(X.value,10));if(isNaN(B.year)||isNaN(B.month)||isNaN(B.day)||isNaN(B.hour)||isNaN(B.minute)||isNaN(B.second))throw Error(`toTZ: Failed to parse all date components from timezone '${Q}'. This may indicate an invalid date or timezone configuration. Parsed components: ${JSON.stringify(B)}`);return B.hour===24&&(B.hour=0),{y:B.year,m:B.month,d:B.day,h:B.hour,i:B.minute,s:B.second,tz:Q}}function j0A(A,Q,w,$,B,X,Y){return{y:A,m:Q,d:w,h:$,i:B,s:X,tz:Y}}var a82=[1,2,4,8,16],r82=class{pattern;timezone;mode;alternativeWeekdays;sloppyRanges;second;minute;hour;day;month;dayOfWeek;year;lastDayOfMonth;lastWeekday;nearestWeekdays;starDOM;starDOW;starYear;useAndLogic;constructor(A,Q,w){this.pattern=A,this.timezone=Q,this.mode=w?.mode??"auto",this.alternativeWeekdays=w?.alternativeWeekdays??!1,this.sloppyRanges=w?.sloppyRanges??!1,this.second=Array(60).fill(0),this.minute=Array(60).fill(0),this.hour=Array(24).fill(0),this.day=Array(31).fill(0),this.month=Array(12).fill(0),this.dayOfWeek=Array(7).fill(0),this.year=Array(1e4).fill(0),this.lastDayOfMonth=!1,this.lastWeekday=!1,this.nearestWeekdays=Array(31).fill(0),this.starDOM=!1,this.starDOW=!1,this.starYear=!1,this.useAndLogic=!1,this.parse()}parse(){if(!(typeof this.pattern=="string"||this.pattern instanceof String))throw TypeError("CronPattern: Pattern has to be of type string.");this.pattern.indexOf("@")>=0&&(this.pattern=this.handleNicknames(this.pattern).trim());let A=this.pattern.match(/\S+/g)||[""],Q=A.length;if(A.length<5||A.length>7)throw TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five, six, or seven space separated parts are required.");if(this.mode!=="auto"){let $;switch(this.mode){case"5-part":$=5;break;case"6-part":$=6;break;case"7-part":$=7;break;case"5-or-6-parts":$=[5,6];break;case"6-or-7-parts":$=[6,7];break;default:$=0}if(!(Array.isArray($)?$.includes(Q):Q===$)){let B=Array.isArray($)?$.join(" or "):$.toString();throw TypeError(`CronPattern: mode '${this.mode}' requires exactly ${B} parts, but pattern '${this.pattern}' has ${Q} parts.`)}}if(A.length===5&&A.unshift("0"),A.length===6&&A.push("*"),A[3].toUpperCase()==="LW"?(this.lastWeekday=!0,A[3]=""):A[3].toUpperCase().indexOf("L")>=0&&(A[3]=A[3].replace(/L/gi,""),this.lastDayOfMonth=!0),A[3]=="*"&&(this.starDOM=!0),A[6]=="*"&&(this.starYear=!0),A[4].length>=3&&(A[4]=this.replaceAlphaMonths(A[4])),A[5].length>=3&&(A[5]=this.alternativeWeekdays?this.replaceAlphaDaysQuartz(A[5]):this.replaceAlphaDays(A[5])),A[5].startsWith("+")&&(this.useAndLogic=!0,A[5]=A[5].substring(1),A[5]===""))throw TypeError("CronPattern: Day-of-week field cannot be empty after '+' modifier.");switch(A[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0&&(A[0]=A[0].replace(/\?/g,"*"),A[1]=A[1].replace(/\?/g,"*"),A[2]=A[2].replace(/\?/g,"*"),A[3]=A[3].replace(/\?/g,"*"),A[4]=A[4].replace(/\?/g,"*"),A[5]=A[5].replace(/\?/g,"*"),A[6]&&(A[6]=A[6].replace(/\?/g,"*"))),this.mode){case"5-part":A[0]="0",A[6]="*";break;case"6-part":A[6]="*";break;case"5-or-6-parts":A[6]="*";break;case"6-or-7-parts":break;case"7-part":case"auto":break}this.throwAtIllegalCharacters(A),this.partToArray("second",A[0],0,1),this.partToArray("minute",A[1],0,1),this.partToArray("hour",A[2],0,1),this.partToArray("day",A[3],-1,1),this.partToArray("month",A[4],-1,1);let w=this.alternativeWeekdays?-1:0;this.partToArray("dayOfWeek",A[5],w,63),this.partToArray("year",A[6],0,1),!this.alternativeWeekdays&&this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,w,$){let B=this[A],X=A==="day"&&this.lastDayOfMonth,Y=A==="day"&&this.lastWeekday;if(Q===""&&!X&&!Y)throw TypeError("CronPattern: configuration entry "+A+" ("+Q+") is empty, check for trailing spaces.");if(Q==="*")return B.fill($);let Z=Q.split(",");if(Z.length>1)for(let H=0;H<Z.length;H++)this.partToArray(A,Z[H],w,$);else Q.indexOf("-")!==-1&&Q.indexOf("/")!==-1?this.handleRangeWithStepping(Q,A,w,$):Q.indexOf("-")!==-1?this.handleRange(Q,A,w,$):Q.indexOf("/")!==-1?this.handleStepping(Q,A,w,$):Q!==""&&this.handleNumber(Q,A,w,$)}throwAtIllegalCharacters(A){for(let Q=0;Q<A.length;Q++)if((Q===3?/[^/*0-9,\-WwLl]+/:Q===5?/[^/*0-9,\-#Ll]+/:/[^/*0-9,\-]+/).test(A[Q]))throw TypeError("CronPattern: configuration entry "+Q+" ("+A[Q]+") contains illegal characters.")}handleNumber(A,Q,w,$){let B=this.extractNth(A,Q),X=A.toUpperCase().includes("W");if(Q!=="day"&&X)throw TypeError("CronPattern: Nearest weekday modifier (W) only allowed in day-of-month.");X&&(Q="nearestWeekdays");let Y=parseInt(B[0],10)+w;if(isNaN(Y))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,Y,B[1]||$)}setPart(A,Q,w){if(!Object.prototype.hasOwnProperty.call(this,A))throw TypeError("CronPattern: Invalid part specified: "+A);if(A==="dayOfWeek"){if(Q===7&&(Q=0),Q<0||Q>6)throw RangeError("CronPattern: Invalid value for dayOfWeek: "+Q);this.setNthWeekdayOfMonth(Q,w);return}if(A==="second"||A==="minute"){if(Q<0||Q>=60)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="hour"){if(Q<0||Q>=24)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="day"||A==="nearestWeekdays"){if(Q<0||Q>=31)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="month"){if(Q<0||Q>=12)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="year"&&(Q<1||Q>=1e4))throw RangeError("CronPattern: Invalid value for "+A+": "+Q+" (supported range: 1-9999)");this[A][Q]=w}validateNotNaN(A,Q){if(isNaN(A))throw TypeError(Q)}validateRange(A,Q,w,$,B){if(A>Q)throw TypeError("CronPattern: From value is larger than to value: '"+B+"'");if(w!==void 0){if(w===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(w>this[$].length)throw TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[$].length+")")}}handleRangeWithStepping(A,Q,w,$){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in ranges with stepping.");let B=this.extractNth(A,Q),X=B[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(X===null)throw TypeError("CronPattern: Syntax error, illegal range with stepping: '"+A+"'");let[,Y,Z,H]=X,W=parseInt(Y,10)+w,K=parseInt(Z,10)+w,U=parseInt(H,10);this.validateNotNaN(W,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(K,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateNotNaN(U,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(W,K,U,Q,A);for(let G=W;G<=K;G+=U)this.setPart(Q,G,B[1]||$)}extractNth(A,Q){let w=A,$;if(w.includes("#")){if(Q!=="dayOfWeek")throw Error("CronPattern: nth (#) only allowed in day-of-week field");$=w.split("#")[1],w=w.split("#")[0]}else if(w.toUpperCase().endsWith("L")){if(Q!=="dayOfWeek")throw Error("CronPattern: L modifier only allowed in day-of-week field (use L alone for day-of-month)");$="L",w=w.slice(0,-1)}return[w,$]}handleRange(A,Q,w,$){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in a range.");let B=this.extractNth(A,Q),X=B[0].split("-");if(X.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let Y=parseInt(X[0],10)+w,Z=parseInt(X[1],10)+w;this.validateNotNaN(Y,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(Z,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateRange(Y,Z,void 0,Q,A);for(let H=Y;H<=Z;H++)this.setPart(Q,H,B[1]||$)}handleStepping(A,Q,w,$){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in parts with stepping.");let B=this.extractNth(A,Q),X=B[0].split("/");if(X.length!==2)throw TypeError("CronPattern: Syntax error, illegal stepping: '"+A+"'");if(this.sloppyRanges)X[0]===""&&(X[0]="*");else{if(X[0]==="")throw TypeError("CronPattern: Syntax error, stepping with missing prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");if(X[0]!=="*")throw TypeError("CronPattern: Syntax error, stepping with numeric prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.")}let Y=0;X[0]!=="*"&&(Y=parseInt(X[0],10)+w);let Z=parseInt(X[1],10);this.validateNotNaN(Z,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(0,this[Q].length-1,Z,Q,A);for(let H=Y;H<this[Q].length;H+=Z)this.setPart(Q,H,B[1]||$)}replaceAlphaDays(A){return A.replace(/-sun/gi,"-7").replace(/sun/gi,"0").replace(/mon/gi,"1").replace(/tue/gi,"2").replace(/wed/gi,"3").replace(/thu/gi,"4").replace(/fri/gi,"5").replace(/sat/gi,"6")}replaceAlphaDaysQuartz(A){return A.replace(/sun/gi,"1").replace(/mon/gi,"2").replace(/tue/gi,"3").replace(/wed/gi,"4").replace(/thu/gi,"5").replace(/fri/gi,"6").replace(/sat/gi,"7")}replaceAlphaMonths(A){return A.replace(/jan/gi,"1").replace(/feb/gi,"2").replace(/mar/gi,"3").replace(/apr/gi,"4").replace(/may/gi,"5").replace(/jun/gi,"6").replace(/jul/gi,"7").replace(/aug/gi,"8").replace(/sep/gi,"9").replace(/oct/gi,"10").replace(/nov/gi,"11").replace(/dec/gi,"12")}handleNicknames(A){let Q=A.trim().toLowerCase();if(Q==="@yearly"||Q==="@annually")return"0 0 1 1 *";if(Q==="@monthly")return"0 0 1 * *";if(Q==="@weekly")return"0 0 * * 0";if(Q==="@daily"||Q==="@midnight")return"0 0 * * *";if(Q==="@hourly")return"0 * * * *";if(Q==="@reboot")throw TypeError("CronPattern: @reboot is not supported in this environment. This is an event-based trigger that requires system startup detection.");return A}setNthWeekdayOfMonth(A,Q){if(typeof Q!="number"&&Q.toUpperCase()==="L")this.dayOfWeek[A]=this.dayOfWeek[A]|32;else if(Q===63)this.dayOfWeek[A]=63;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|a82[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},N0A=[31,28,31,30,31,30,31,31,30,31,30,31],g8=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],J4=class A{tz;ms;second;minute;hour;day;month;year;constructor(Q,w){if(this.tz=w,Q&&Q instanceof Date)if(!isNaN(Q))this.fromDate(Q);else throw TypeError("CronDate: Invalid date passed to CronDate constructor");else if(Q==null)this.fromDate(new Date);else if(Q&&typeof Q=="string")this.fromString(Q);else if(Q instanceof A)this.fromCronDate(Q);else throw TypeError("CronDate: Invalid type ("+typeof Q+") passed to CronDate constructor")}getLastDayOfMonth(Q,w){return w!==1?N0A[w]:new Date(Date.UTC(Q,w+1,0)).getUTCDate()}getLastWeekday(Q,w){let $=this.getLastDayOfMonth(Q,w),B=new Date(Date.UTC(Q,w,$)).getUTCDay();return B===0?$-2:B===6?$-1:$}getNearestWeekday(Q,w,$){let B=this.getLastDayOfMonth(Q,w);if($>B)return-1;let X=new Date(Date.UTC(Q,w,$)).getUTCDay();return X===0?$===B?$-2:$+1:X===6?$===1?$+2:$-1:$}isNthWeekdayOfMonth(Q,w,$,B){let X=new Date(Date.UTC(Q,w,$)).getUTCDay(),Y=0;for(let Z=1;Z<=$;Z++)new Date(Date.UTC(Q,w,Z)).getUTCDay()===X&&Y++;if(B&63&&a82[Y-1]&B)return!0;if(B&32){let Z=this.getLastDayOfMonth(Q,w);for(let H=$+1;H<=Z;H++)if(new Date(Date.UTC(Q,w,H)).getUTCDay()===X)return!1;return!0}return!1}fromDate(Q){if(this.tz!==void 0)if(typeof this.tz=="number")this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes()+this.tz,this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),this.apply();else try{let w=Ka(Q,this.tz);this.ms=Q.getMilliseconds(),this.second=w.s,this.minute=w.i,this.hour=w.h,this.day=w.d,this.month=w.m-1,this.year=w.y}catch(w){let $=w instanceof Error?w.message:String(w);throw TypeError(`CronDate: Failed to convert date to timezone '${this.tz}'. This may happen with invalid timezone names or dates. Original error: ${$}`)}else this.ms=Q.getMilliseconds(),this.second=Q.getSeconds(),this.minute=Q.getMinutes(),this.hour=Q.getHours(),this.day=Q.getDate(),this.month=Q.getMonth(),this.year=Q.getFullYear()}fromCronDate(Q){this.tz=Q.tz,this.year=Q.year,this.month=Q.month,this.day=Q.day,this.hour=Q.hour,this.minute=Q.minute,this.second=Q.second,this.ms=Q.ms}apply(){if(this.month>11||this.month<0||this.day>N0A[this.month]||this.day<1||this.hour>59||this.minute>59||this.second>59||this.hour<0||this.minute<0||this.second<0){let Q=new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms));return this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes(),this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),!0}else return!1}fromString(Q){if(typeof this.tz=="number"){let w=n82(Q);this.ms=w.getUTCMilliseconds(),this.second=w.getUTCSeconds(),this.minute=w.getUTCMinutes(),this.hour=w.getUTCHours(),this.day=w.getUTCDate(),this.month=w.getUTCMonth(),this.year=w.getUTCFullYear(),this.apply()}else return this.fromDate(n82(Q,this.tz))}findNext(Q,w,$,B){return this._findMatch(Q,w,$,B,1)}_findMatch(Q,w,$,B,X){let Y=this[w],Z;$.lastDayOfMonth&&(Z=this.getLastDayOfMonth(this.year,this.month));let H=!$.starDOW&&w=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0,W=this[w]+B,K=X===1?(U)=>U<$[w].length:(U)=>U>=0;for(let U=W;K(U);U+=X){let G=$[w][U];if(w==="day"&&!G){for(let q=0;q<$.nearestWeekdays.length;q++)if($.nearestWeekdays[q]){let V=this.getNearestWeekday(this.year,this.month,q-B);if(V===-1)continue;if(V===U-B){G=1;break}}}if(w==="day"&&$.lastWeekday){let q=this.getLastWeekday(this.year,this.month);U-B===q&&(G=1)}if(w==="day"&&$.lastDayOfMonth&&U-B==Z&&(G=1),w==="day"&&!$.starDOW){let q=$.dayOfWeek[(H+(U-B-1))%7];if(q&&q&63)q=this.isNthWeekdayOfMonth(this.year,this.month,U-B,q)?1:0;else if(q)throw Error(`CronDate: Invalid value for dayOfWeek encountered. ${q}`);$.useAndLogic?G=G&&q:!Q.domAndDow&&!$.starDOM?G=G||q:G=G&&q}if(G)return this[w]=U-B,Y!==this[w]?2:1}return 3}recurse(Q,w,$){if($===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let X=-1;for(let Y=this.year+1;Y<Q.year.length&&Y<1e4;Y++)if(Q.year[Y]===1){X=Y;break}if(X===-1)return null;this.year=X,this.month=0,this.day=1,this.hour=0,this.minute=0,this.second=0,this.ms=0}if(this.year>=1e4)return null}let B=this.findNext(w,g8[$][0],Q,g8[$][2]);if(B>1){let X=$+1;for(;X<g8.length;)this[g8[X][0]]=-g8[X][2],X++;if(B===3){if(this[g8[$][1]]++,this[g8[$][0]]=-g8[$][2],this.apply(),$===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0&&this.year<1e4;)this.year++;if(this.year>=1e4||this.year>=Q.year.length)return null}return this.recurse(Q,w,0)}else if(this.apply())return this.recurse(Q,w,$-1)}return $+=1,$>=g8.length?this:(Q.starYear?this.year>=3000:this.year>=1e4)?null:this.recurse(Q,w,$)}increment(Q,w,$){return this.second+=w.interval!==void 0&&w.interval>1&&$?w.interval:1,this.ms=0,this.apply(),this.recurse(Q,w,0)}decrement(Q,w){return this.second-=w.interval!==void 0&&w.interval>1?w.interval:1,this.ms=0,this.apply(),this.recurseBackward(Q,w,0,0)}recurseBackward(Q,w,$,B=0){if(B>1e4)return null;if($===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let Y=-1;for(let Z=this.year-1;Z>=0;Z--)if(Q.year[Z]===1){Y=Z;break}if(Y===-1)return null;this.year=Y,this.month=11,this.day=31,this.hour=23,this.minute=59,this.second=59,this.ms=0}if(this.year<0)return null}let X=this.findPrevious(w,g8[$][0],Q,g8[$][2]);if(X>1){let Y=$+1;for(;Y<g8.length;){let Z=g8[Y][0],H=g8[Y][2],W=this.getMaxPatternValue(Z,Q,H);this[Z]=W,Y++}if(X===3){if(this[g8[$][1]]--,$===0){let K=this.getLastDayOfMonth(this.year,this.month);this.day>K&&(this.day=K)}if($===1)if(this.day<=0)this.day=1;else{let K=this.year,U=this.month;for(;U<0;)U+=12,K--;for(;U>11;)U-=12,K++;let G=U!==1?N0A[U]:new Date(Date.UTC(K,U+1,0)).getUTCDate();this.day>G&&(this.day=G)}this.apply();let Z=g8[$][0],H=g8[$][2],W=this.getMaxPatternValue(Z,Q,H);if(Z==="day"){let K=this.getLastDayOfMonth(this.year,this.month);this[Z]=Math.min(W,K)}else this[Z]=W;if(this.apply(),$===0){let K=g8[1][2],U=this.getMaxPatternValue("day",Q,K),G=this.getLastDayOfMonth(this.year,this.month),q=Math.min(U,G);q!==this.day&&(this.day=q,this.hour=this.getMaxPatternValue("hour",Q,g8[2][2]),this.minute=this.getMaxPatternValue("minute",Q,g8[3][2]),this.second=this.getMaxPatternValue("second",Q,g8[4][2]))}if($===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0;)this.year--;if(this.year<0)return null}return this.recurseBackward(Q,w,0,B+1)}else if(this.apply())return this.recurseBackward(Q,w,$-1,B+1)}return $+=1,$>=g8.length?this:this.year<0?null:this.recurseBackward(Q,w,$,B+1)}getMaxPatternValue(Q,w,$){if(Q==="day"&&w.lastDayOfMonth)return this.getLastDayOfMonth(this.year,this.month);if(Q==="day"&&!w.starDOW)return this.getLastDayOfMonth(this.year,this.month);for(let B=w[Q].length-1;B>=0;B--)if(w[Q][B])return B-$;return w[Q].length-1-$}findPrevious(Q,w,$,B){return this._findMatch(Q,w,$,B,-1)}getDate(Q){return Q||this.tz===void 0?new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms):typeof this.tz=="number"?new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute-this.tz,this.second,this.ms)):s82(j0A(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}match(Q,w){if(!Q.starYear&&(this.year<0||this.year>=Q.year.length||Q.year[this.year]===0))return!1;for(let $=0;$<g8.length;$++){let B=g8[$][0],X=g8[$][2],Y=this[B];if(Y+X<0||Y+X>=Q[B].length)return!1;let Z=Q[B][Y+X];if(B==="day"){if(!Z){for(let H=0;H<Q.nearestWeekdays.length;H++)if(Q.nearestWeekdays[H]){let W=this.getNearestWeekday(this.year,this.month,H-X);if(W!==-1&&W===Y){Z=1;break}}}if(Q.lastWeekday){let H=this.getLastWeekday(this.year,this.month);Y===H&&(Z=1)}if(Q.lastDayOfMonth){let H=this.getLastDayOfMonth(this.year,this.month);Y===H&&(Z=1)}if(!Q.starDOW){let H=new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay(),W=Q.dayOfWeek[(H+(Y-1))%7];W&&W&63&&(W=this.isNthWeekdayOfMonth(this.year,this.month,Y,W)?1:0),Q.useAndLogic?Z=Z&&W:!w.domAndDow&&!Q.starDOM?Z=Z||W:Z=Z&&W}}if(!Z)return!1}return!0}};function JOw(A){if(A===void 0&&(A={}),delete A.name,A.legacyMode!==void 0&&A.domAndDow===void 0?A.domAndDow=!A.legacyMode:A.domAndDow===void 0&&(A.domAndDow=!1),A.legacyMode=!A.domAndDow,A.paused=A.paused===void 0?!1:A.paused,A.maxRuns=A.maxRuns===void 0?1/0:A.maxRuns,A.catch=A.catch===void 0?!1:A.catch,A.interval=A.interval===void 0?0:parseInt(A.interval.toString(),10),A.utcOffset=A.utcOffset===void 0?void 0:parseInt(A.utcOffset.toString(),10),A.dayOffset=A.dayOffset===void 0?0:parseInt(A.dayOffset.toString(),10),A.unref=A.unref===void 0?!1:A.unref,A.mode=A.mode===void 0?"auto":A.mode,A.alternativeWeekdays=A.alternativeWeekdays===void 0?!1:A.alternativeWeekdays,A.sloppyRanges=A.sloppyRanges===void 0?!1:A.sloppyRanges,!["auto","5-part","6-part","7-part","5-or-6-parts","6-or-7-parts"].includes(A.mode))throw Error("CronOptions: mode must be one of 'auto', '5-part', '6-part', '7-part', '5-or-6-parts', or '6-or-7-parts'.");if(A.startAt&&(A.startAt=new J4(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new J4(A.stopAt,A.timezone)),A.interval!==null){if(isNaN(A.interval))throw Error("CronOptions: Supplied value for interval is not a number");if(A.interval<0)throw Error("CronOptions: Supplied value for interval can not be negative")}if(A.utcOffset!==void 0){if(isNaN(A.utcOffset))throw Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");if(A.utcOffset<-870||A.utcOffset>870)throw Error("CronOptions: utcOffset out of bounds.");if(A.utcOffset!==void 0&&A.timezone)throw Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.")}if(A.unref!==!0&&A.unref!==!1)throw Error("CronOptions: Unref should be either true, false or undefined(false).");if(A.dayOffset!==void 0&&A.dayOffset!==0&&isNaN(A.dayOffset))throw Error("CronOptions: Invalid value passed for dayOffset, should be a number representing days to offset.");return A}function Ua(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function FOw(A){return Ua(A)}function IOw(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var o82=30000,CH0=[],P0A=class{name;options;_states;fn;getTz(){return this.options.timezone||this.options.utcOffset}applyDayOffset(A){if(this.options.dayOffset!==void 0&&this.options.dayOffset!==0){let Q=this.options.dayOffset*24*60*60*1000;return new Date(A.getTime()+Q)}return A}constructor(A,Q,w){let $,B;if(Ua(Q))B=Q;else if(typeof Q=="object")$=Q;else if(Q!==void 0)throw Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(Ua(w))B=w;else if(typeof w=="object")$=w;else if(w!==void 0)throw Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=$?.name,this.options=JOw($),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:$?$.maxRuns:void 0,paused:$?$.paused:!1,pattern:new r82("* * * * *",void 0,{mode:"auto"})},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new J4(A,this.getTz()):this._states.pattern=new r82(A,this.options.timezone,{mode:this.options.mode,alternativeWeekdays:this.options.alternativeWeekdays,sloppyRanges:this.options.sloppyRanges}),this.name){if(CH0.find((X)=>X.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");CH0.push(this)}return B!==void 0&&FOw(B)&&(this.fn=B,this.schedule()),this}nextRun(A){let Q=this._next(A);return Q?this.applyDayOffset(Q.getDate(!1)):null}nextRuns(A,Q){this._states.maxRuns!==void 0&&A>this._states.maxRuns&&(A=this._states.maxRuns);let w=Q||this._states.currentRun||void 0;return this._enumerateRuns(A,w,"next")}previousRuns(A,Q){return this._enumerateRuns(A,Q||void 0,"previous")}_enumerateRuns(A,Q,w){let $=[],B=Q?new J4(Q,this.getTz()):null,X=w==="next"?this._next:this._previous;for(;A--;){let Y=X.call(this,B);if(!Y)break;let Z=Y.getDate(!1);$.push(this.applyDayOffset(Z)),B=Y}return $}match(A){if(this._states.once){let w=new J4(A,this.getTz());w.ms=0;let $=new J4(this._states.once,this.getTz());return $.ms=0,w.getTime()===$.getTime()}let Q=new J4(A,this.getTz());return Q.ms=0,Q.match(this._states.pattern,this.options)}getPattern(){if(!this._states.once)return this._states.pattern?this._states.pattern.pattern:void 0}getOnce(){return this._states.once?this._states.once.getDate():null}isRunning(){let A=this.nextRun(this._states.currentRun),Q=!this._states.paused,w=this.fn!==void 0,$=!this._states.kill;return Q&&w&&$&&A!==null}isStopped(){return this._states.kill}isBusy(){return this._states.blocking}currentRun(){return this._states.currentRun?this._states.currentRun.getDate():null}previousRun(){return this._states.previousRun?this._states.previousRun.getDate():null}msToNext(A){let Q=this._next(A);return Q?A instanceof J4||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new J4(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=CH0.indexOf(this);A>=0&&CH0.splice(A,1)}pause(){return this._states.paused=!0,!this._states.kill}resume(){return this._states.paused=!1,!this._states.kill}schedule(A){if(A&&this.fn)throw Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");A&&(this.fn=A);let Q=this.msToNext(),w=this.nextRun(this._states.currentRun);return Q==null||isNaN(Q)||w===null?this:(Q>o82&&(Q=o82),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(w),Q),this._states.currentTimeout&&this.options.unref&&IOw(this._states.currentTimeout),this)}async _trigger(A){this._states.blocking=!0,this._states.currentRun=new J4(void 0,this.getTz());try{if(this.options.catch)try{this.fn!==void 0&&await this.fn(this,this.options.context)}catch(Q){if(Ua(this.options.catch))try{this.options.catch(Q,this)}catch{}}else this.fn!==void 0&&await this.fn(this,this.options.context)}finally{this._states.previousRun=new J4(A,this.getTz()),this._states.blocking=!1}}async trigger(){await this._trigger()}runsLeft(){return this._states.maxRuns}_checkTrigger(A){let Q=new Date,w=!this._states.paused&&Q.getTime()>=A.getTime(),$=this._states.blocking&&this.options.protect;w&&!$?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):w&&$&&Ua(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()}_next(A){let Q=!!(A||this._states.currentRun),w=!1;!A&&this.options.startAt&&this.options.interval&&([A,Q]=this._calculatePreviousRun(A,Q),w=!A),A=new J4(A,this.getTz()),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let $=this._states.once||new J4(A,this.getTz());return!w&&$!==this._states.once&&($=$.increment(this._states.pattern,this.options,Q)),this._states.once&&this._states.once.getTime()<=A.getTime()||$===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&$.getTime()>=this.options.stopAt.getTime()?null:$}_previous(A){let Q=new J4(A,this.getTz());this.options.stopAt&&Q.getTime()>this.options.stopAt.getTime()&&(Q=this.options.stopAt);let w=new J4(Q,this.getTz());return this._states.once?this._states.once.getTime()<Q.getTime()?this._states.once:null:(w=w.decrement(this._states.pattern,this.options),w===null||this.options.startAt&&w.getTime()<this.options.startAt.getTime()?null:w)}_calculatePreviousRun(A,Q){let w=new J4(void 0,this.getTz()),$=A;if(this.options.startAt.getTime()<=w.getTime()){$=this.options.startAt;let B=$.getTime()+this.options.interval*1000;for(;B<=w.getTime();)$=new J4($,this.getTz()).increment(this._states.pattern,this.options,!0),B=$.getTime()+this.options.interval*1000;Q=!0}return $===null&&($=void 0),[$,Q]}};class yH0{scheduleCron(A,Q){let w=new P0A(A,()=>{Q()});return{stop:()=>w.stop()}}scheduleInterval(A,Q){let w=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(w)}}validateCron(A){new P0A(A).stop()}}C0();var t82=f.union([f.string().min(1),f.object({location:f.enum(["metadata","frontmatter"]),field:f.string().min(1)})]),gH0=f.object({entityType:f.string().min(1),attachmentType:f.string().min(1),mediaEntityType:f.enum(["image","document"]),targetEntityField:t82.optional(),requiredWhen:f.object({status:f.string().min(1).optional(),visibility:f.string().min(1).optional()}).optional(),autoGenerate:f.boolean().optional(),requiredForPublish:f.boolean().optional(),jobType:f.string().min(1).optional()});function M0A(A){return`${A.entityType}:${A.attachmentType}`}class dq{static instance=null;definitions=new Map;static getInstance(){return dq.instance??=new dq,dq.instance}static resetInstance(){dq.instance=null}static createFresh(){return new dq}constructor(){}register(A){let Q=gH0.parse(A),w=M0A(Q);return this.definitions.set(w,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(M0A({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(M0A({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}K7();k2();class EH0{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 O0A(A.metadata[Q]);if(Q.location==="metadata")return O0A(A.metadata[Q.field]);let{frontmatter:w}=p6(A.content);return O0A(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 q1(`${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 O0A(A){return typeof A==="string"?A.length>0:A!==void 0}fA();C0();var bOw=f.object({id:f.string().min(1)});async function AB2(A,Q){let{bodyContent:w,coverImageId:$,documents:B,sourceEntityType:X,sourceEntityId:Y}=LOw(Q.content),Z=$?await NOw(A,$):void 0,H;if(B&&B.length>0){let K=await jOw(A,B);if(K.length>0)H=K}H??=await _Ow(A,X,Y);let W={bodyContent:w};if(Z)W.imageData=Z;if(H&&H.length>0)W.documentData=H;return W}function LOw(A){try{let Q=BQ(A,f.record(f.string(),f.unknown())),w=Q.metadata.coverImageId,$=typeof w==="string"?w:void 0,B=kOw(Q.metadata.documents),X=e82(Q.metadata.sourceEntityType),Y=e82(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...$&&{coverImageId:$},...B.length>0&&{documents:B},...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}}}catch{return{bodyContent:A}}}function kOw(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let w=bOw.safeParse(Q);return w.success?[w.data]:[]})}function e82(A){return typeof A==="string"&&A.length>0?A:void 0}async function _Ow(A,Q,w){if(!Q||!w)return;let $=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:w,attachmentType:"carousel"});return $?[$]:void 0}async function NOw(A,Q){let w=await A.entityService.getEntity({entityType:"image",id:Q});if(!w?.content)return;let $=QB2(w.content);if(!$?.mimeType.startsWith("image/"))return;return{data:$.data,mimeType:$.mimeType}}async function jOw(A,Q){return(await Promise.all(Q.map(($)=>POw(A,$)))).filter(($)=>$!==void 0)}async function POw(A,Q){let w=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!w?.content)return;let $=QB2(w.content);if($?.mimeType!=="application/pdf")return;return{type:"document",data:$.data,mimeType:"application/pdf",filename:MOw(w,Q.id)}}function QB2(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function MOw(A,Q){let w=A.metadata.filename;return typeof w==="string"&&w.length>0?w:`${Q}.pdf`}K7();var OOw=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function x0A(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,...xOw(w.id,$.publishResultIdField)},H={...Q,content:wB2(Q.content,Y,w.id,$.publishResultIdField,B),metadata:Z};return await A.entityService.updateEntity({entity:H}),H}function wB2(A,Q,w,$,B="publishedAt"){if(!OOw.test(A))return A;let X=u4(u4(A,"status","published"),B,Q);if(!w||!$)return X;return u4(X,$,w)}function xOw(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class sE{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 AB2(this.deps.context,w),H=await B.publish(X,w.metadata,Y,Z),W=this.deps.providerRegistry.getPublishResultIdField($),K=this.deps.providerRegistry.getPublishTimestampField($),U=await x0A(this.deps.context,w,H,{...W?{publishResultIdField:W}:{},...K?{publishTimestampField:K}:{}});return await this.runPublishAssetPreflight(U),{entity:U,result:H}}async runPublishAssetPreflight(A){if(!this.deps.publishAssetPreflight)return;try{await this.deps.publishAssetPreflight.ensureForEntity(A)}catch(Q){this.deps.context.logger.warn("Publish asset preflight failed",{entityType:A.entityType,entityId:A.id,error:Q instanceof Error?Q.message:String(Q)})}}async findPublishableEntity(A,Q,w){if(Q)return this.deps.context.entityService.getEntity({entityType:A,id:Q});if(!w)return null;return(await this.deps.context.entityService.listEntities({entityType:A,options:{filter:{metadata:{slug:w}},limit:1}}))[0]??null}}fA();C0();var R0A=f.object({action:f.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:f.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:f.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:f.number().optional().describe("New position for reorder action (1-based)")}),v0A=f.object({position:f.number(),entityType:f.string(),entityId:f.string(),queuedAt:f.string()}),ROw=f.object({success:f.literal(!0),message:f.string().optional(),data:f.object({queue:f.array(v0A).optional(),entityType:f.string().optional(),entityId:f.string().optional(),position:f.number().optional()}).optional()}),vOw=f.object({success:f.literal(!1),error:f.string(),code:f.string().optional()}),h0A=f.union([ROw,vOw]);function TH0(A,Q,w){return{...i6(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",R0A,async(B,X)=>{let{action:Y,entityType:Z,entityId:H,position:W}=B;switch(Y){case"list":return hOw(w,Z);case"add":return COw(A,w,Z,H,X);case"remove":return yOw(A,w,Z,H,X);case"reorder":return gOw(A,w,Z,H,W,X);default:return{success:!1,error:`Unknown action: ${Y}`}}},{sideEffects:"writes"}),outputSchema:h0A}}async function hOw(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 COw(A,Q,w,$,B){let X=C0A("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 yOw(A,Q,w,$,B){let X=C0A("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 gOw(A,Q,w,$,B,X){let Y=C0A("reorder",w,$);if(!Y.success)return Y.error;let Z=EOw(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 C0A(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 EOw(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}}C0();import{createHash as TOw}from"crypto";var y0A=f.object({entityType:f.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:f.string().optional().describe("Entity ID to publish"),slug:f.string().optional().describe("Entity slug to publish"),confirmed:f.boolean().optional(),confirmationToken:f.string().optional(),contentHash:f.string().optional(),expiresAt:f.string().datetime().optional()}),SOw=f.object({entityType:f.string(),id:f.string().optional(),slug:f.string().optional(),confirmed:f.boolean().optional(),confirmationToken:f.string().optional(),contentHash:f.string().optional(),expiresAt:f.string().datetime().optional()}),mOw=f.object({success:f.literal(!0),message:f.string().optional(),data:f.object({entityType:f.string().optional(),entityId:f.string().optional(),platformId:f.string().optional(),url:f.string().optional()}).optional()}),uOw=f.object({success:f.literal(!1),error:f.string(),code:f.string().optional()}),cOw=f.object({success:f.literal(!1).optional(),error:f.string().optional(),needsConfirmation:f.literal(!0),toolName:f.string(),summary:f.string(),preview:f.string().optional(),args:f.unknown()}),g0A=f.union([mOw,uOw,cOw]),lOw=900000;function SH0(A,Q,w,$){let B=$??new sE({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:y0A.shape,outputSchema:g0A,visibility:"anchor",sideEffects:"external",handler:async(Y,Z)=>{let H=SOw.safeParse(Y);if(!H.success)return{success:!1,error:`Invalid input: ${H.error.issues.map((J)=>`${J.path.join(".")}: ${J.message}`).join(", ")}`};let W=H.data,{entityType:K,id:U,slug:G}=W;try{A.permissions.assertEntityActionAllowed(K,"publish",Z)}catch(J){return{success:!1,error:J instanceof Error?J.message:String(J)}}let q=await B.resolveCandidate({entityType:K,id:U,slug:G});if("error"in q)return{success:!1,error:q.error};let{entity:V}=q;if(W.confirmed){let J=iOw(X,W,V);if(J!==null)return J;let F;try{F=await B.publish({entityType:K,id:V.id})}catch(_){return{success:!1,error:_ instanceof Error?_.message:String(_)}}if("error"in F)return{success:!1,error:F.error};let{entity:k,result:j}=F;return{success:!0,data:{entityType:K,entityId:k.id,platformId:j.id,url:j.url},message:`Published ${K}:${k.id}`}}return pOw(X,W,V)}}}function pOw(A,Q,w){let $=new Date(Date.now()+lOw).toISOString(),B=$B2(A,w,$),X=dOw(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 iOw(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($!==$B2(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 $B2(A,Q,w){return TOw("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 dOw(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}fA();C0();var E0A=f.object({entityType:f.string().min(1).describe("Entity type to reconcile"),status:f.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:f.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),T0A=f.object({success:f.literal(!0),data:f.object({entityType:f.string(),assetType:f.string().optional(),checkedEntities:f.number(),checkedAssets:f.number(),enqueued:f.number(),skipped:f.number()}),message:f.string().optional()});function mH0(A,Q,w,$){return{...i6(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",E0A,async(X,Y)=>{if(A.permissions.assertEntityActionAllowed(X.entityType,"publish",Y),w.list(X.entityType).filter((G)=>G.autoGenerate===!0).filter((G)=>!X.assetType||G.attachmentType===X.assetType).length===0)return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:0,checkedAssets:0,enqueued:0,skipped:0},message:`No publish assets configured for ${X.entityType}`};let H=await A.entityService.listEntities({entityType:X.entityType,options:{...X.status&&{filter:{metadata:{status:X.status}}}}}),W=0,K=0,U=0;for(let G of H){let q=await $.ensureForEntity(G,{...X.assetType&&{attachmentType:X.assetType}});W+=q.checked,K+=q.enqueued,U+=q.skipped}return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:H.length,checkedAssets:W,enqueued:K,skipped:U},message:`Queued ${K} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:T0A}}fA();function BB2(A,Q){nOw(A,Q),rOw(A,Q),oOw(A,Q),sOw(A,Q)}function nOw(A,Q){A.messaging.subscribe(_Y.REGISTER,async(w)=>aOw(Q,w.payload)),A.messaging.subscribe(_Y.QUEUE,async(w)=>Qxw(A,Q,w.payload)),A.messaging.subscribe(_Y.DIRECT,async(w)=>wxw(A,Q,w.payload)),A.messaging.subscribe(_Y.REMOVE,async(w)=>$xw(Q,w.payload)),A.messaging.subscribe(_Y.REORDER,async(w)=>Bxw(Q,w.payload)),A.messaging.subscribe(_Y.LIST,async(w)=>Xxw(A,Q,w.payload)),A.messaging.subscribe(_Y.REPORT_SUCCESS,async(w)=>Yxw(Q,w.payload)),A.messaging.subscribe(_Y.REPORT_FAILURE,async(w)=>Zxw(Q,w.payload)),Q.logger.debug("Subscribed to publish messages")}function rOw(A,Q){A.messaging.subscribe(CL.REPORT_SUCCESS,async(w)=>fxw(Q,w.payload)),A.messaging.subscribe(CL.REPORT_FAILURE,async(w)=>Hxw(Q,w.payload)),Q.logger.debug("Subscribed to generation messages")}function oOw(A,Q){A.messaging.subscribe(S82.REGISTER,async(w)=>tOw(Q,w.payload)),Q.logger.debug("Subscribed to publish asset messages")}function sOw(A,Q){let w=async($)=>eOw(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 aOw(A,Q){let{entityType:w,provider:$,config:B}=Q;try{let X=B?m82.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=dA(X);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function tOw(A,Q){let w=gH0.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 eOw(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(!Axw($))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:dA($)}),{success:!1}}}function Axw(A){if(!A)return!1;let Q=T82.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function Qxw(A,Q,w){let{entityType:$,entityId:B}=w;try{let X=w.authContext??Ha;A.permissions.assertEntityActionAllowed($,"publish",X);let Y=await Q.queueManager.add($,B,X);return await A.messaging.send({type:_Y.QUEUED,payload:{entityType:$,entityId:B,position:Y.position}}),Q.logger.debug(`Entity queued: ${B}`,{entityType:$,position:Y.position}),{success:!0}}catch(X){let Y=dA(X);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function wxw(A,Q,w){let{entityType:$,entityId:B}=w,X=w.authContext??Ha;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=dA(Y);return Q.logger.error(`Failed direct publish request: ${Z}`),{success:!1}}}async function $xw(A,Q){let{entityType:w,entityId:$}=Q;try{return await A.queueManager.remove(w,$),A.logger.debug(`Entity removed from queue: ${$}`,{entityType:w}),{success:!0}}catch(B){let X=dA(B);return A.logger.error(`Failed to remove entity: ${X}`),{success:!1}}}async function Bxw(A,Q){let{entityType:w,entityId:$,position:B}=Q;try{return await A.queueManager.reorder(w,$,B),A.logger.debug(`Entity reordered: ${$}`,{entityType:w,newPosition:B}),{success:!0}}catch(X){let Y=dA(X);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function Xxw(A,Q,w){let{entityType:$}=w;try{let B=await Q.queueManager.list($);return await A.messaging.send({type:_Y.LIST_RESPONSE,payload:{entityType:$,queue:B.map((X)=>({entityId:X.entityId,position:X.position,queuedAt:X.queuedAt}))}}),{success:!0}}catch(B){let X=dA(B);return Q.logger.error(`Failed to list queue: ${X}`),{success:!1}}}async function Yxw(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 Zxw(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 fxw(A,Q){let{entityType:w,entityId:$}=Q;return A.scheduler.completeGeneration(w,$),A.logger.info("Generation completed",{entityType:w,entityId:$}),{success:!0}}async function Hxw(A,Q){let{entityType:w,error:$}=Q;return A.scheduler.failGeneration(w,$),A.logger.warn("Generation failed",{entityType:w,error:$}),{success:!0}}async function XB2(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:dA(B)}),{shouldGenerate:!1,reason:`Condition check failed: ${dA(B)}`}}}function YB2(A){let{context:Q,config:w,queueManager:$,providerRegistry:B,retryTracker:X,publishExecutor:Y,logger:Z}=A,H=Wxw(Q);return zG.createFresh({queueManager:$,providerRegistry:B,retryTracker:X,logger:Z,backend:new yH0,...w.entitySchedules&&{entitySchedules:w.entitySchedules},...w.generationSchedules&&{generationSchedules:w.generationSchedules},...w.generationConditions&&{generationConditions:w.generationConditions},messageBus:H,publishExecutor:Y,onCheckGenerationConditions:(W,K)=>XB2(Q.entityService,Z,W,K)})}function Wxw(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:()=>{}}}async function ZB2(A,Q,w){let $=A.getEntityTypes();for(let X of $){let Y=await A.listEntities({entityType:X,options:{filter:{metadata:{status:"queued"}}}});for(let Z of Y)await Q.add(Z.entityType,Z.id)}let B=0;for(let X of $){let Y=await Q.list(X);B+=Y.length}if(B>0)w.info(`Rebuilt queue with ${B} queued entities`)}C0();var Kxw=["draft","queued","published","failed"];async function fB2(A,Q){await A.messaging.send({type:"dashboard:register-widget",payload:{id:"publication-pipeline",pluginId:Q,title:"Publication Pipeline",group:"publishing",section:"secondary",priority:100,rendererName:"PipelineWidget",visibility:"anchor",dataProvider:()=>zxw(A),digestProvider:Gxw}})}var Uxw=f.object({summary:f.object({draft:f.number(),queued:f.number(),published:f.number(),failed:f.number()}),generating:f.array(f.unknown())});function Gxw(A){let{summary:Q,generating:w}=Uxw.parse(A),$=Q.queued+w.length,B=$===0?"idle":`${Q.queued} queued \xB7 ${w.length} generating`,X=Q.failed>0?`${Q.draft} drafts \xB7 ${Q.failed} failed`:`${Q.draft} drafts`,Y=Q.draft+Q.failed;return{digest:[{label:"Pipeline",value:B,...$>0?{tone:"warn"}:{}},{label:"Awaiting review",value:X,...Y>0?{tone:"warn"}:{}},{label:"Published",value:String(Q.published),tone:"good"}],needsOperator:Y}}var Dxw=f.object({sourceEntityType:f.string(),sourceEntityId:f.string(),attachmentType:f.string().optional()});async function qxw(A){let Q=await A.jobs.getActiveJobs(),w=[];for(let $ of Q){if($.source!=="content-pipeline")continue;if($.status!=="pending"&&$.status!=="processing")continue;let B;try{B=JSON.parse($.data)}catch{continue}let X=Dxw.safeParse(B);if(!X.success)continue;w.push({id:$.id,label:X.data.attachmentType??$.type,target:`${X.data.sourceEntityType}/${X.data.sourceEntityId}`,status:$.status})}return w}async function zxw(A){let Q=A.entityService.getEntityTypes(),w=[],$={draft:0,queued:0,published:0,failed:0};for(let B of Q){let X=await A.entityService.listEntities({entityType:B});for(let Y of X){let Z=Vxw(Y.metadata.status);if(!Z)continue;$[Z]++,w.push({id:Y.id,title:Jxw(Y.id,Y.metadata.title),type:B,status:Z})}}return{summary:$,items:w,generating:await qxw(A)}}function Vxw(A){return Kxw.find((Q)=>Q===A)}function Jxw(A,Q){return typeof Q==="string"?Q:A}var HB2={name:"@brains/content-pipeline",version:"0.2.0-alpha.168",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",croner:"^10.0.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^7.0.2"},exports:{".":{types:"./src/index.ts",default:"./src/index.ts"}},files:["src"],main:"src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"src/index.ts"};class S0A extends Uw{pluginContext;queueManager;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",HB2,A,u82)}async onRegister(A){this.pluginContext=A,this.queueManager=lq.createFresh(),this.providerRegistry=pq.createFresh(),this.retryTracker=iq.createFresh(),this.publishAssetRegistry=dq.createFresh(),this.publishAssetPreflight=new EH0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new sE({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=YB2({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),BB2(A,{queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,publishAssetRegistry:this.publishAssetRegistry,publishAssetPreflight:this.publishAssetPreflight,scheduler:this.scheduler,logger:this.logger})}async onReady(A){await ZB2(A.entityService,this.queueManager,this.logger),await fB2(A,this.id),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[TH0(this.pluginContext,this.id,this.queueManager),SH0(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),mH0(this.pluginContext,this.id,this.publishAssetRegistry,this.publishAssetPreflight)]}async getInstructions(){return'## Publishing\n- Use `content-pipeline_queue` to manage the publish queue \u2014 list queued items, add entities to the queue, remove them, or reorder.\n- Use `content-pipeline_publish` to publish an entity directly to its platform (e.g. LinkedIn, Buttondown). This tool has its own confirmation flow; call it without `confirmed` when the user asks to publish instead of asking for plain-text confirmation. Follow-up requests like "publish it now" should target the entity just read, generated, or updated in the conversation, including a post just changed to draft.\n- Use `content-pipeline_ensure-assets` to reconcile missing publish assets such as generated OG images for already-published content.\n- When users ask about their "publish queue", "publishing queue", or "what\'s queued", use `content-pipeline_queue`.'}getQueueManager(){return this.queueManager}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getPublishAssetRegistry(){return this.publishAssetRegistry}getScheduler(){return this.scheduler}async onShutdown(){await this.scheduler.stop(),lq.resetInstance(),pq.resetInstance(),iq.resetInstance(),dq.resetInstance()}}function m0A(A={}){return new S0A(A)}fA();C0();var WB2=f.object({accountId:f.string().describe("Cloudflare account ID"),apiToken:f.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:f.string().describe("Cloudflare Web Analytics site tag")}),u0A=f.object({cloudflare:WB2.optional()});fA();C0();var Ixw=f.object({date:f.string().describe("Single date in YYYY-MM-DD format").optional(),days:f.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:f.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:f.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:f.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function bxw(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 KB2(A,Q,w){let $=[];if(!w)return $;return $.push(i6(A,"query",`Query website analytics from Cloudflare.
|
|
7973
|
+
${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=fOw.parse(Q),$=[],B=gX.from(async(W)=>{let K={progress:W.progress};if(W.message!==void 0)K.message=W.message;$.push(K)});if(!B)throw Error("Failed to create progress reporter");let Y=await new kM(A.logger,A).process(w,`eval-${Date.now()}`,B),Z=!1,H;if(Y.success&&Y.entityId){let W=await A.entityService.getEntity({entityType:"social-post",id:Y.entityId});Z=!!W,H=W?.content.slice(0,300)}return{...Y,entityExists:Z,entityPreview:H,progressSteps:$}})}fA();class Za{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=BQ(B.content,qG),H;if(Z.metadata.coverImageId)H=await this.fetchImageData(Z.metadata.coverImageId);let W=Z.metadata.documents??[],K=await this.fetchDocumentData(W);try{if(W.length>0&&K.length===0)throw Error(`Refusing to publish: ${W.length} document(s) referenced but none could be fetched`);let U=W.length===0?await this.resolveSourceAttachment(Z.metadata):[],G=K.length>0?K:U,q=G.length?await Y.publish(Z.content,B.metadata,H,G):await Y.publish(Z.content,B.metadata,H),V=new Date().toISOString(),J=q.id||void 0,F={...Z.metadata,status:"published",publishedAt:V,...J&&{platformPostId:J}},k=V4.createPostContent(F,Z.content);await this.entityService.updateEntity({entity:{...B,content:k,metadata:{...B.metadata,status:"published",publishedAt:V,platformPostId:J}}}),await this.reportSuccess(Q,w,q.id),this.logger.info(`Post published successfully: ${w}`,{platform:X,platformPostId:J})}catch(U){let G=U instanceof Error?U.message:String(U),q={...Z.metadata,status:"failed"},V=V4.createPostContent(q,Z.content);await this.entityService.updateEntity({entity:{...B,content:V,metadata:{...B.metadata,status:"failed"}}}),await this.reportFailure(Q,w,G),this.logger.error(`Post publish failed: ${w}`,{platform:X,error:G})}}catch($){let B=dA($);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 R82(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 v82(A,Q,w){let $=new Za({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 h82(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 H=dA(Z);return Q.error(`Failed to trigger auto-generate for ${B}:`,{error:H}),{success:!0}}}),Q.debug("Subscribed to entity:updated for auto-generation")}function C82(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:`${V4.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=dA(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 y82(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:`${V4.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=dA(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 g82({entity:A,config:Q}){let w=hL.parse(A),$=V4.parsePostFrontmatter(w),B=V4.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 J0A(){return{entityType:"social-post",collection:"ai.rizom.brain.socialPost",lexicon:m6["ai.rizom.brain.socialPost"],validate:!1,buildRecord:g82}}var E82={name:"@brains/social-media",version:"0.2.0-alpha.169",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 F0A extends fw{entityType=V4.entityType;schema=hL;adapter=V4;providers=new Map;unregisterAtprotoProjection;constructor(A={}){super("social-media",E82,A,U0A)}createGenerationHandler(A){return new kM(this.logger.child("GenerationJobHandler"),A)}getTemplates(){return O82()}getDataSources(){return[new xH0(this.logger.child("SocialPostDataSource"))]}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}async onRegister(A){if(this.initializeProviders(),R82(A,this.providers,this.logger),v82(A,this.providers,this.logger),this.config.autoGenerateOnBlogPublish)h82(A,this.logger),C82(A,this.logger),this.logger.info("Auto-generate on blog publish enabled");y82(A,this.logger),x82(A),this.unregisterAtprotoProjection=NB.getInstance().register(J0A()),this.logger.info("Social media plugin registered successfully")}async onShutdown(){this.unregisterAtprotoProjection?.(),this.unregisterAtprotoProjection=void 0}initializeProviders(){if(this.config.linkedin?.accessToken){let A=V0A(this.config.linkedin,this.logger.child("LinkedInClient"));this.providers.set("linkedin",A),this.logger.info("LinkedIn provider initialized")}}}function fa(A={}){return new F0A(A)}C0();var WOw=f.enum(["draft","queued","published","failed"]),T82=f.object({status:WOw.default("draft"),queueOrder:f.number().optional().describe("Position in publish queue (lower = sooner)"),publishedAt:f.string().datetime().optional()});class I0A{name="internal";async publish(A,Q){return{id:"internal"}}}var Ha={interfaceType:"system",userId:"system",userPermissionLevel:"anchor",authorization:"system"},_Y={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"},CL={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"},S82={REGISTER:"publish-assets:register"};C0();var KOw=f.enum(["provider"]),m82=f.object({executionMode:KOw.optional(),publishResultIdField:f.string().min(1).optional(),publishTimestampField:f.string().min(1).optional(),enabled:f.boolean().optional()}).strict();var UOw=f.object({skipIfDraftExists:f.boolean().optional(),minSourceEntities:f.number().optional(),maxUnpublishedDrafts:f.number().optional(),sourceEntityType:f.string().optional()}),u82=f.object({entitySchedules:f.record(f.string(),f.string()).optional(),generationSchedules:f.record(f.string(),f.string()).optional(),generationConditions:f.record(f.string(),UOw).optional()});class lq{static instance=null;queues=new Map;static getInstance(){return lq.instance??=new lq,lq.instance}static resetInstance(){lq.instance=null}static createFresh(){return new lq}constructor(){}async add(A,Q,w=Ha){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}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 pq{static instance=null;providers=new Map;executionModes=new Map;publishResultIdFields=new Map;publishTimestampFields=new Map;defaultProvider=new I0A;static getInstance(){return pq.instance??=new pq,pq.instance}static resetInstance(){pq.instance=null}static createFresh(){return new pq}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 c82(A,Q){if(!Q.publishExecutor){Q.onFailed?.({entityType:A.entityType,entityId:A.entityId,error:"Publish executor not configured",retryCount:0,willRetry:!1});return}await GOw(A,Q)}async function GOw(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:_Y.FAILED,payload:$,sender:"publish-service",broadcast:!0});Q.onFailed?.($);return}b0A(A.entityType,A.entityId,w.result,Q)}catch(w){let $=dA(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 b0A(A,Q,w,$){if($.retryTracker.clearRetries(Q),$.messageBus)$.messageBus.send({type:_Y.COMPLETED,payload:{entityType:A,entityId:Q,result:w},sender:"publish-service",broadcast:!0});$.onPublish?.({entityType:A,entityId:Q,result:w})}function l82(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:_Y.FAILED,payload:X,sender:"publish-service",broadcast:!0});$.onFailed?.(X)}async function p82(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:CL.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:CL.EXECUTE,payload:$,sender:"content-pipeline"});Q.onGenerate?.($)}function i82(A,Q,w){if(w)w.send({type:CL.COMPLETED,payload:{entityType:A,entityId:Q},sender:"content-pipeline"})}function d82(A,Q,w){if(w)w.send({type:CL.FAILED,payload:{entityType:A,error:Q},sender:"content-pipeline"})}var DOw=1000;class L0A{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(DOw,()=>this.processUnscheduledTypes())}stop(){if(qOw(this.publishJobs),this.immediateIntervalJob)this.immediateIntervalJob.stop(),this.immediateIntervalJob=null}async processEntityType(A){if(!this.deps.isRunning())return;try{let Q=await this.deps.config.queueManager.getNext(A);if(Q)await this.processEntry(Q)}catch(Q){this.deps.config.logger.error(`Scheduler error for ${A}:`,Q)}}async processUnscheduledTypes(){if(!this.deps.isRunning())return;try{let A=await this.deps.config.queueManager.getQueuedEntityTypes();for(let Q of A)if(!this.entitySchedules[Q]){let w=await this.deps.config.queueManager.getNext(Q);if(w){await this.processEntry(w);break}}}catch(A){this.deps.config.logger.error("Scheduler error for unscheduled types:",A)}}async processEntry(A){await this.deps.config.queueManager.remove(A.entityType,A.entityId);let Q=this.deps.getPublishDeps();await c82(A,Q)}get entitySchedules(){return this.deps.config.entitySchedules}}function qOw(A){for(let Q of A.values())Q.stop();A.clear()}class k0A{deps;generationJobs=new Map;constructor(A){this.deps=A}start(){for(let[A,Q]of Object.entries(this.generationSchedules)){let w=this.deps.config.backend.scheduleCron(Q,()=>this.handleTriggerGeneration(A));this.generationJobs.set(A,w)}}stop(){zOw(this.generationJobs)}async handleTriggerGeneration(A){if(!this.deps.isRunning())return;try{await p82(A,this.deps.getGenerationDeps())}catch(Q){this.deps.config.logger.error(`Generation trigger error for ${A}:`,Q)}}get generationSchedules(){return this.deps.config.generationSchedules}}function zOw(A){for(let Q of A.values())Q.stop();A.clear()}class zG{static instance=null;config;publishRunner;generationRunner;running=!1;static getInstance(A){return zG.instance??=new zG(A),zG.instance}static resetInstance(){if(zG.instance)zG.instance.stop();zG.instance=null}static createFresh(A){return new zG(A)}constructor(A){this.config={...A,entitySchedules:A.entitySchedules??{},generationSchedules:A.generationSchedules??{},generationConditions:A.generationConditions??{}},this.validateCronExpressions(),this.publishRunner=new L0A({config:this.config,getPublishDeps:()=>this.publishDeps,isRunning:()=>this.running}),this.generationRunner=new k0A({config:this.config,getGenerationDeps:()=>this.generationDeps,isRunning:()=>this.running})}async start(){if(this.running)return;this.running=!0,this.publishRunner.start(),this.generationRunner.start()}async stop(){this.running=!1,this.publishRunner.stop(),this.generationRunner.stop()}isRunning(){return this.running}completePublish(A,Q,w){b0A(A,Q,w,this.publishDeps)}failPublish(A,Q,w){l82(A,Q,w,this.publishDeps)}completeGeneration(A,Q){i82(A,Q,this.config.messageBus)}failGeneration(A,Q){d82(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}" - ${dA($)}`,{cause:$})}}}class iq{static instance=null;retries=new Map;static getInstance(){return iq.instance??=new iq,iq.instance}static resetInstance(){iq.instance=null}static createFresh(){return new iq}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}}}function Wa(A){return Date.UTC(A.y,A.m-1,A.d,A.h,A.i,A.s)}function _0A(A,Q){return A.y===Q.y&&A.m===Q.m&&A.d===Q.d&&A.h===Q.h&&A.i===Q.i&&A.s===Q.s}function VOw(A,Q){let w=new Date(Date.parse(A));if(isNaN(w))throw Error("Invalid ISO8601 passed to timezone parser.");let $=A.substring(9);return $.includes("Z")||$.includes("+")||$.includes("-")?j0A(w.getUTCFullYear(),w.getUTCMonth()+1,w.getUTCDate(),w.getUTCHours(),w.getUTCMinutes(),w.getUTCSeconds(),"Etc/UTC"):j0A(w.getFullYear(),w.getMonth()+1,w.getDate(),w.getHours(),w.getMinutes(),w.getSeconds(),Q)}function n82(A,Q,w){return s82(VOw(A,Q),w)}function s82(A,Q){let w=new Date(Wa(A)),$=Ka(w,A.tz),B=Wa(A),X=Wa($),Y=B-X,Z=new Date(w.getTime()+Y),H=Ka(Z,A.tz);if(_0A(H,A)){let U=new Date(Z.getTime()-3600000),G=Ka(U,A.tz);return _0A(G,A)?U:Z}let W=new Date(Z.getTime()+Wa(A)-Wa(H)),K=Ka(W,A.tz);if(_0A(K,A))return W;if(Q)throw Error("Invalid date passed to fromTZ()");return Z.getTime()>W.getTime()?Z:W}function Ka(A,Q){let w,$;try{w=new Intl.DateTimeFormat("en-US",{timeZone:Q,year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric",hour12:!1}),$=w.formatToParts(A)}catch(X){let Y=X instanceof Error?X.message:String(X);throw RangeError(`toTZ: Invalid timezone '${Q}' or date. Please provide a valid IANA timezone (e.g., 'America/New_York', 'Europe/Stockholm'). Original error: ${Y}`)}let B={year:0,month:0,day:0,hour:0,minute:0,second:0};for(let X of $)(X.type==="year"||X.type==="month"||X.type==="day"||X.type==="hour"||X.type==="minute"||X.type==="second")&&(B[X.type]=parseInt(X.value,10));if(isNaN(B.year)||isNaN(B.month)||isNaN(B.day)||isNaN(B.hour)||isNaN(B.minute)||isNaN(B.second))throw Error(`toTZ: Failed to parse all date components from timezone '${Q}'. This may indicate an invalid date or timezone configuration. Parsed components: ${JSON.stringify(B)}`);return B.hour===24&&(B.hour=0),{y:B.year,m:B.month,d:B.day,h:B.hour,i:B.minute,s:B.second,tz:Q}}function j0A(A,Q,w,$,B,X,Y){return{y:A,m:Q,d:w,h:$,i:B,s:X,tz:Y}}var a82=[1,2,4,8,16],r82=class{pattern;timezone;mode;alternativeWeekdays;sloppyRanges;second;minute;hour;day;month;dayOfWeek;year;lastDayOfMonth;lastWeekday;nearestWeekdays;starDOM;starDOW;starYear;useAndLogic;constructor(A,Q,w){this.pattern=A,this.timezone=Q,this.mode=w?.mode??"auto",this.alternativeWeekdays=w?.alternativeWeekdays??!1,this.sloppyRanges=w?.sloppyRanges??!1,this.second=Array(60).fill(0),this.minute=Array(60).fill(0),this.hour=Array(24).fill(0),this.day=Array(31).fill(0),this.month=Array(12).fill(0),this.dayOfWeek=Array(7).fill(0),this.year=Array(1e4).fill(0),this.lastDayOfMonth=!1,this.lastWeekday=!1,this.nearestWeekdays=Array(31).fill(0),this.starDOM=!1,this.starDOW=!1,this.starYear=!1,this.useAndLogic=!1,this.parse()}parse(){if(!(typeof this.pattern=="string"||this.pattern instanceof String))throw TypeError("CronPattern: Pattern has to be of type string.");this.pattern.indexOf("@")>=0&&(this.pattern=this.handleNicknames(this.pattern).trim());let A=this.pattern.match(/\S+/g)||[""],Q=A.length;if(A.length<5||A.length>7)throw TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five, six, or seven space separated parts are required.");if(this.mode!=="auto"){let $;switch(this.mode){case"5-part":$=5;break;case"6-part":$=6;break;case"7-part":$=7;break;case"5-or-6-parts":$=[5,6];break;case"6-or-7-parts":$=[6,7];break;default:$=0}if(!(Array.isArray($)?$.includes(Q):Q===$)){let B=Array.isArray($)?$.join(" or "):$.toString();throw TypeError(`CronPattern: mode '${this.mode}' requires exactly ${B} parts, but pattern '${this.pattern}' has ${Q} parts.`)}}if(A.length===5&&A.unshift("0"),A.length===6&&A.push("*"),A[3].toUpperCase()==="LW"?(this.lastWeekday=!0,A[3]=""):A[3].toUpperCase().indexOf("L")>=0&&(A[3]=A[3].replace(/L/gi,""),this.lastDayOfMonth=!0),A[3]=="*"&&(this.starDOM=!0),A[6]=="*"&&(this.starYear=!0),A[4].length>=3&&(A[4]=this.replaceAlphaMonths(A[4])),A[5].length>=3&&(A[5]=this.alternativeWeekdays?this.replaceAlphaDaysQuartz(A[5]):this.replaceAlphaDays(A[5])),A[5].startsWith("+")&&(this.useAndLogic=!0,A[5]=A[5].substring(1),A[5]===""))throw TypeError("CronPattern: Day-of-week field cannot be empty after '+' modifier.");switch(A[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0&&(A[0]=A[0].replace(/\?/g,"*"),A[1]=A[1].replace(/\?/g,"*"),A[2]=A[2].replace(/\?/g,"*"),A[3]=A[3].replace(/\?/g,"*"),A[4]=A[4].replace(/\?/g,"*"),A[5]=A[5].replace(/\?/g,"*"),A[6]&&(A[6]=A[6].replace(/\?/g,"*"))),this.mode){case"5-part":A[0]="0",A[6]="*";break;case"6-part":A[6]="*";break;case"5-or-6-parts":A[6]="*";break;case"6-or-7-parts":break;case"7-part":case"auto":break}this.throwAtIllegalCharacters(A),this.partToArray("second",A[0],0,1),this.partToArray("minute",A[1],0,1),this.partToArray("hour",A[2],0,1),this.partToArray("day",A[3],-1,1),this.partToArray("month",A[4],-1,1);let w=this.alternativeWeekdays?-1:0;this.partToArray("dayOfWeek",A[5],w,63),this.partToArray("year",A[6],0,1),!this.alternativeWeekdays&&this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(A,Q,w,$){let B=this[A],X=A==="day"&&this.lastDayOfMonth,Y=A==="day"&&this.lastWeekday;if(Q===""&&!X&&!Y)throw TypeError("CronPattern: configuration entry "+A+" ("+Q+") is empty, check for trailing spaces.");if(Q==="*")return B.fill($);let Z=Q.split(",");if(Z.length>1)for(let H=0;H<Z.length;H++)this.partToArray(A,Z[H],w,$);else Q.indexOf("-")!==-1&&Q.indexOf("/")!==-1?this.handleRangeWithStepping(Q,A,w,$):Q.indexOf("-")!==-1?this.handleRange(Q,A,w,$):Q.indexOf("/")!==-1?this.handleStepping(Q,A,w,$):Q!==""&&this.handleNumber(Q,A,w,$)}throwAtIllegalCharacters(A){for(let Q=0;Q<A.length;Q++)if((Q===3?/[^/*0-9,\-WwLl]+/:Q===5?/[^/*0-9,\-#Ll]+/:/[^/*0-9,\-]+/).test(A[Q]))throw TypeError("CronPattern: configuration entry "+Q+" ("+A[Q]+") contains illegal characters.")}handleNumber(A,Q,w,$){let B=this.extractNth(A,Q),X=A.toUpperCase().includes("W");if(Q!=="day"&&X)throw TypeError("CronPattern: Nearest weekday modifier (W) only allowed in day-of-month.");X&&(Q="nearestWeekdays");let Y=parseInt(B[0],10)+w;if(isNaN(Y))throw TypeError("CronPattern: "+Q+" is not a number: '"+A+"'");this.setPart(Q,Y,B[1]||$)}setPart(A,Q,w){if(!Object.prototype.hasOwnProperty.call(this,A))throw TypeError("CronPattern: Invalid part specified: "+A);if(A==="dayOfWeek"){if(Q===7&&(Q=0),Q<0||Q>6)throw RangeError("CronPattern: Invalid value for dayOfWeek: "+Q);this.setNthWeekdayOfMonth(Q,w);return}if(A==="second"||A==="minute"){if(Q<0||Q>=60)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="hour"){if(Q<0||Q>=24)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="day"||A==="nearestWeekdays"){if(Q<0||Q>=31)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="month"){if(Q<0||Q>=12)throw RangeError("CronPattern: Invalid value for "+A+": "+Q)}else if(A==="year"&&(Q<1||Q>=1e4))throw RangeError("CronPattern: Invalid value for "+A+": "+Q+" (supported range: 1-9999)");this[A][Q]=w}validateNotNaN(A,Q){if(isNaN(A))throw TypeError(Q)}validateRange(A,Q,w,$,B){if(A>Q)throw TypeError("CronPattern: From value is larger than to value: '"+B+"'");if(w!==void 0){if(w===0)throw TypeError("CronPattern: Syntax error, illegal stepping: 0");if(w>this[$].length)throw TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[$].length+")")}}handleRangeWithStepping(A,Q,w,$){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in ranges with stepping.");let B=this.extractNth(A,Q),X=B[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(X===null)throw TypeError("CronPattern: Syntax error, illegal range with stepping: '"+A+"'");let[,Y,Z,H]=X,W=parseInt(Y,10)+w,K=parseInt(Z,10)+w,U=parseInt(H,10);this.validateNotNaN(W,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(K,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateNotNaN(U,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(W,K,U,Q,A);for(let G=W;G<=K;G+=U)this.setPart(Q,G,B[1]||$)}extractNth(A,Q){let w=A,$;if(w.includes("#")){if(Q!=="dayOfWeek")throw Error("CronPattern: nth (#) only allowed in day-of-week field");$=w.split("#")[1],w=w.split("#")[0]}else if(w.toUpperCase().endsWith("L")){if(Q!=="dayOfWeek")throw Error("CronPattern: L modifier only allowed in day-of-week field (use L alone for day-of-month)");$="L",w=w.slice(0,-1)}return[w,$]}handleRange(A,Q,w,$){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in a range.");let B=this.extractNth(A,Q),X=B[0].split("-");if(X.length!==2)throw TypeError("CronPattern: Syntax error, illegal range: '"+A+"'");let Y=parseInt(X[0],10)+w,Z=parseInt(X[1],10)+w;this.validateNotNaN(Y,"CronPattern: Syntax error, illegal lower range (NaN)"),this.validateNotNaN(Z,"CronPattern: Syntax error, illegal upper range (NaN)"),this.validateRange(Y,Z,void 0,Q,A);for(let H=Y;H<=Z;H++)this.setPart(Q,H,B[1]||$)}handleStepping(A,Q,w,$){if(A.toUpperCase().includes("W"))throw TypeError("CronPattern: Syntax error, W is not allowed in parts with stepping.");let B=this.extractNth(A,Q),X=B[0].split("/");if(X.length!==2)throw TypeError("CronPattern: Syntax error, illegal stepping: '"+A+"'");if(this.sloppyRanges)X[0]===""&&(X[0]="*");else{if(X[0]==="")throw TypeError("CronPattern: Syntax error, stepping with missing prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.");if(X[0]!=="*")throw TypeError("CronPattern: Syntax error, stepping with numeric prefix ('"+A+"') is not allowed. Use wildcard (*/step) or range (min-max/step) instead.")}let Y=0;X[0]!=="*"&&(Y=parseInt(X[0],10)+w);let Z=parseInt(X[1],10);this.validateNotNaN(Z,"CronPattern: Syntax error, illegal stepping: (NaN)"),this.validateRange(0,this[Q].length-1,Z,Q,A);for(let H=Y;H<this[Q].length;H+=Z)this.setPart(Q,H,B[1]||$)}replaceAlphaDays(A){return A.replace(/-sun/gi,"-7").replace(/sun/gi,"0").replace(/mon/gi,"1").replace(/tue/gi,"2").replace(/wed/gi,"3").replace(/thu/gi,"4").replace(/fri/gi,"5").replace(/sat/gi,"6")}replaceAlphaDaysQuartz(A){return A.replace(/sun/gi,"1").replace(/mon/gi,"2").replace(/tue/gi,"3").replace(/wed/gi,"4").replace(/thu/gi,"5").replace(/fri/gi,"6").replace(/sat/gi,"7")}replaceAlphaMonths(A){return A.replace(/jan/gi,"1").replace(/feb/gi,"2").replace(/mar/gi,"3").replace(/apr/gi,"4").replace(/may/gi,"5").replace(/jun/gi,"6").replace(/jul/gi,"7").replace(/aug/gi,"8").replace(/sep/gi,"9").replace(/oct/gi,"10").replace(/nov/gi,"11").replace(/dec/gi,"12")}handleNicknames(A){let Q=A.trim().toLowerCase();if(Q==="@yearly"||Q==="@annually")return"0 0 1 1 *";if(Q==="@monthly")return"0 0 1 * *";if(Q==="@weekly")return"0 0 * * 0";if(Q==="@daily"||Q==="@midnight")return"0 0 * * *";if(Q==="@hourly")return"0 * * * *";if(Q==="@reboot")throw TypeError("CronPattern: @reboot is not supported in this environment. This is an event-based trigger that requires system startup detection.");return A}setNthWeekdayOfMonth(A,Q){if(typeof Q!="number"&&Q.toUpperCase()==="L")this.dayOfWeek[A]=this.dayOfWeek[A]|32;else if(Q===63)this.dayOfWeek[A]=63;else if(Q<6&&Q>0)this.dayOfWeek[A]=this.dayOfWeek[A]|a82[Q-1];else throw TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${Q}, Type: ${typeof Q}`)}},N0A=[31,28,31,30,31,30,31,31,30,31,30,31],g8=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],J4=class A{tz;ms;second;minute;hour;day;month;year;constructor(Q,w){if(this.tz=w,Q&&Q instanceof Date)if(!isNaN(Q))this.fromDate(Q);else throw TypeError("CronDate: Invalid date passed to CronDate constructor");else if(Q==null)this.fromDate(new Date);else if(Q&&typeof Q=="string")this.fromString(Q);else if(Q instanceof A)this.fromCronDate(Q);else throw TypeError("CronDate: Invalid type ("+typeof Q+") passed to CronDate constructor")}getLastDayOfMonth(Q,w){return w!==1?N0A[w]:new Date(Date.UTC(Q,w+1,0)).getUTCDate()}getLastWeekday(Q,w){let $=this.getLastDayOfMonth(Q,w),B=new Date(Date.UTC(Q,w,$)).getUTCDay();return B===0?$-2:B===6?$-1:$}getNearestWeekday(Q,w,$){let B=this.getLastDayOfMonth(Q,w);if($>B)return-1;let X=new Date(Date.UTC(Q,w,$)).getUTCDay();return X===0?$===B?$-2:$+1:X===6?$===1?$+2:$-1:$}isNthWeekdayOfMonth(Q,w,$,B){let X=new Date(Date.UTC(Q,w,$)).getUTCDay(),Y=0;for(let Z=1;Z<=$;Z++)new Date(Date.UTC(Q,w,Z)).getUTCDay()===X&&Y++;if(B&63&&a82[Y-1]&B)return!0;if(B&32){let Z=this.getLastDayOfMonth(Q,w);for(let H=$+1;H<=Z;H++)if(new Date(Date.UTC(Q,w,H)).getUTCDay()===X)return!1;return!0}return!1}fromDate(Q){if(this.tz!==void 0)if(typeof this.tz=="number")this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes()+this.tz,this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),this.apply();else try{let w=Ka(Q,this.tz);this.ms=Q.getMilliseconds(),this.second=w.s,this.minute=w.i,this.hour=w.h,this.day=w.d,this.month=w.m-1,this.year=w.y}catch(w){let $=w instanceof Error?w.message:String(w);throw TypeError(`CronDate: Failed to convert date to timezone '${this.tz}'. This may happen with invalid timezone names or dates. Original error: ${$}`)}else this.ms=Q.getMilliseconds(),this.second=Q.getSeconds(),this.minute=Q.getMinutes(),this.hour=Q.getHours(),this.day=Q.getDate(),this.month=Q.getMonth(),this.year=Q.getFullYear()}fromCronDate(Q){this.tz=Q.tz,this.year=Q.year,this.month=Q.month,this.day=Q.day,this.hour=Q.hour,this.minute=Q.minute,this.second=Q.second,this.ms=Q.ms}apply(){if(this.month>11||this.month<0||this.day>N0A[this.month]||this.day<1||this.hour>59||this.minute>59||this.second>59||this.hour<0||this.minute<0||this.second<0){let Q=new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms));return this.ms=Q.getUTCMilliseconds(),this.second=Q.getUTCSeconds(),this.minute=Q.getUTCMinutes(),this.hour=Q.getUTCHours(),this.day=Q.getUTCDate(),this.month=Q.getUTCMonth(),this.year=Q.getUTCFullYear(),!0}else return!1}fromString(Q){if(typeof this.tz=="number"){let w=n82(Q);this.ms=w.getUTCMilliseconds(),this.second=w.getUTCSeconds(),this.minute=w.getUTCMinutes(),this.hour=w.getUTCHours(),this.day=w.getUTCDate(),this.month=w.getUTCMonth(),this.year=w.getUTCFullYear(),this.apply()}else return this.fromDate(n82(Q,this.tz))}findNext(Q,w,$,B){return this._findMatch(Q,w,$,B,1)}_findMatch(Q,w,$,B,X){let Y=this[w],Z;$.lastDayOfMonth&&(Z=this.getLastDayOfMonth(this.year,this.month));let H=!$.starDOW&&w=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0,W=this[w]+B,K=X===1?(U)=>U<$[w].length:(U)=>U>=0;for(let U=W;K(U);U+=X){let G=$[w][U];if(w==="day"&&!G){for(let q=0;q<$.nearestWeekdays.length;q++)if($.nearestWeekdays[q]){let V=this.getNearestWeekday(this.year,this.month,q-B);if(V===-1)continue;if(V===U-B){G=1;break}}}if(w==="day"&&$.lastWeekday){let q=this.getLastWeekday(this.year,this.month);U-B===q&&(G=1)}if(w==="day"&&$.lastDayOfMonth&&U-B==Z&&(G=1),w==="day"&&!$.starDOW){let q=$.dayOfWeek[(H+(U-B-1))%7];if(q&&q&63)q=this.isNthWeekdayOfMonth(this.year,this.month,U-B,q)?1:0;else if(q)throw Error(`CronDate: Invalid value for dayOfWeek encountered. ${q}`);$.useAndLogic?G=G&&q:!Q.domAndDow&&!$.starDOM?G=G||q:G=G&&q}if(G)return this[w]=U-B,Y!==this[w]?2:1}return 3}recurse(Q,w,$){if($===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let X=-1;for(let Y=this.year+1;Y<Q.year.length&&Y<1e4;Y++)if(Q.year[Y]===1){X=Y;break}if(X===-1)return null;this.year=X,this.month=0,this.day=1,this.hour=0,this.minute=0,this.second=0,this.ms=0}if(this.year>=1e4)return null}let B=this.findNext(w,g8[$][0],Q,g8[$][2]);if(B>1){let X=$+1;for(;X<g8.length;)this[g8[X][0]]=-g8[X][2],X++;if(B===3){if(this[g8[$][1]]++,this[g8[$][0]]=-g8[$][2],this.apply(),$===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0&&this.year<1e4;)this.year++;if(this.year>=1e4||this.year>=Q.year.length)return null}return this.recurse(Q,w,0)}else if(this.apply())return this.recurse(Q,w,$-1)}return $+=1,$>=g8.length?this:(Q.starYear?this.year>=3000:this.year>=1e4)?null:this.recurse(Q,w,$)}increment(Q,w,$){return this.second+=w.interval!==void 0&&w.interval>1&&$?w.interval:1,this.ms=0,this.apply(),this.recurse(Q,w,0)}decrement(Q,w){return this.second-=w.interval!==void 0&&w.interval>1?w.interval:1,this.ms=0,this.apply(),this.recurseBackward(Q,w,0,0)}recurseBackward(Q,w,$,B=0){if(B>1e4)return null;if($===0&&!Q.starYear){if(this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0){let Y=-1;for(let Z=this.year-1;Z>=0;Z--)if(Q.year[Z]===1){Y=Z;break}if(Y===-1)return null;this.year=Y,this.month=11,this.day=31,this.hour=23,this.minute=59,this.second=59,this.ms=0}if(this.year<0)return null}let X=this.findPrevious(w,g8[$][0],Q,g8[$][2]);if(X>1){let Y=$+1;for(;Y<g8.length;){let Z=g8[Y][0],H=g8[Y][2],W=this.getMaxPatternValue(Z,Q,H);this[Z]=W,Y++}if(X===3){if(this[g8[$][1]]--,$===0){let K=this.getLastDayOfMonth(this.year,this.month);this.day>K&&(this.day=K)}if($===1)if(this.day<=0)this.day=1;else{let K=this.year,U=this.month;for(;U<0;)U+=12,K--;for(;U>11;)U-=12,K++;let G=U!==1?N0A[U]:new Date(Date.UTC(K,U+1,0)).getUTCDate();this.day>G&&(this.day=G)}this.apply();let Z=g8[$][0],H=g8[$][2],W=this.getMaxPatternValue(Z,Q,H);if(Z==="day"){let K=this.getLastDayOfMonth(this.year,this.month);this[Z]=Math.min(W,K)}else this[Z]=W;if(this.apply(),$===0){let K=g8[1][2],U=this.getMaxPatternValue("day",Q,K),G=this.getLastDayOfMonth(this.year,this.month),q=Math.min(U,G);q!==this.day&&(this.day=q,this.hour=this.getMaxPatternValue("hour",Q,g8[2][2]),this.minute=this.getMaxPatternValue("minute",Q,g8[3][2]),this.second=this.getMaxPatternValue("second",Q,g8[4][2]))}if($===0&&!Q.starYear){for(;this.year>=0&&this.year<Q.year.length&&Q.year[this.year]===0;)this.year--;if(this.year<0)return null}return this.recurseBackward(Q,w,0,B+1)}else if(this.apply())return this.recurseBackward(Q,w,$-1,B+1)}return $+=1,$>=g8.length?this:this.year<0?null:this.recurseBackward(Q,w,$,B+1)}getMaxPatternValue(Q,w,$){if(Q==="day"&&w.lastDayOfMonth)return this.getLastDayOfMonth(this.year,this.month);if(Q==="day"&&!w.starDOW)return this.getLastDayOfMonth(this.year,this.month);for(let B=w[Q].length-1;B>=0;B--)if(w[Q][B])return B-$;return w[Q].length-1-$}findPrevious(Q,w,$,B){return this._findMatch(Q,w,$,B,-1)}getDate(Q){return Q||this.tz===void 0?new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms):typeof this.tz=="number"?new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute-this.tz,this.second,this.ms)):s82(j0A(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}match(Q,w){if(!Q.starYear&&(this.year<0||this.year>=Q.year.length||Q.year[this.year]===0))return!1;for(let $=0;$<g8.length;$++){let B=g8[$][0],X=g8[$][2],Y=this[B];if(Y+X<0||Y+X>=Q[B].length)return!1;let Z=Q[B][Y+X];if(B==="day"){if(!Z){for(let H=0;H<Q.nearestWeekdays.length;H++)if(Q.nearestWeekdays[H]){let W=this.getNearestWeekday(this.year,this.month,H-X);if(W!==-1&&W===Y){Z=1;break}}}if(Q.lastWeekday){let H=this.getLastWeekday(this.year,this.month);Y===H&&(Z=1)}if(Q.lastDayOfMonth){let H=this.getLastDayOfMonth(this.year,this.month);Y===H&&(Z=1)}if(!Q.starDOW){let H=new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay(),W=Q.dayOfWeek[(H+(Y-1))%7];W&&W&63&&(W=this.isNthWeekdayOfMonth(this.year,this.month,Y,W)?1:0),Q.useAndLogic?Z=Z&&W:!w.domAndDow&&!Q.starDOM?Z=Z||W:Z=Z&&W}}if(!Z)return!1}return!0}};function JOw(A){if(A===void 0&&(A={}),delete A.name,A.legacyMode!==void 0&&A.domAndDow===void 0?A.domAndDow=!A.legacyMode:A.domAndDow===void 0&&(A.domAndDow=!1),A.legacyMode=!A.domAndDow,A.paused=A.paused===void 0?!1:A.paused,A.maxRuns=A.maxRuns===void 0?1/0:A.maxRuns,A.catch=A.catch===void 0?!1:A.catch,A.interval=A.interval===void 0?0:parseInt(A.interval.toString(),10),A.utcOffset=A.utcOffset===void 0?void 0:parseInt(A.utcOffset.toString(),10),A.dayOffset=A.dayOffset===void 0?0:parseInt(A.dayOffset.toString(),10),A.unref=A.unref===void 0?!1:A.unref,A.mode=A.mode===void 0?"auto":A.mode,A.alternativeWeekdays=A.alternativeWeekdays===void 0?!1:A.alternativeWeekdays,A.sloppyRanges=A.sloppyRanges===void 0?!1:A.sloppyRanges,!["auto","5-part","6-part","7-part","5-or-6-parts","6-or-7-parts"].includes(A.mode))throw Error("CronOptions: mode must be one of 'auto', '5-part', '6-part', '7-part', '5-or-6-parts', or '6-or-7-parts'.");if(A.startAt&&(A.startAt=new J4(A.startAt,A.timezone)),A.stopAt&&(A.stopAt=new J4(A.stopAt,A.timezone)),A.interval!==null){if(isNaN(A.interval))throw Error("CronOptions: Supplied value for interval is not a number");if(A.interval<0)throw Error("CronOptions: Supplied value for interval can not be negative")}if(A.utcOffset!==void 0){if(isNaN(A.utcOffset))throw Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");if(A.utcOffset<-870||A.utcOffset>870)throw Error("CronOptions: utcOffset out of bounds.");if(A.utcOffset!==void 0&&A.timezone)throw Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.")}if(A.unref!==!0&&A.unref!==!1)throw Error("CronOptions: Unref should be either true, false or undefined(false).");if(A.dayOffset!==void 0&&A.dayOffset!==0&&isNaN(A.dayOffset))throw Error("CronOptions: Invalid value passed for dayOffset, should be a number representing days to offset.");return A}function Ua(A){return Object.prototype.toString.call(A)==="[object Function]"||typeof A=="function"||A instanceof Function}function FOw(A){return Ua(A)}function IOw(A){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(A):A&&typeof A.unref<"u"&&A.unref()}var o82=30000,CH0=[],P0A=class{name;options;_states;fn;getTz(){return this.options.timezone||this.options.utcOffset}applyDayOffset(A){if(this.options.dayOffset!==void 0&&this.options.dayOffset!==0){let Q=this.options.dayOffset*24*60*60*1000;return new Date(A.getTime()+Q)}return A}constructor(A,Q,w){let $,B;if(Ua(Q))B=Q;else if(typeof Q=="object")$=Q;else if(Q!==void 0)throw Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(Ua(w))B=w;else if(typeof w=="object")$=w;else if(w!==void 0)throw Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=$?.name,this.options=JOw($),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:$?$.maxRuns:void 0,paused:$?$.paused:!1,pattern:new r82("* * * * *",void 0,{mode:"auto"})},A&&(A instanceof Date||typeof A=="string"&&A.indexOf(":")>0)?this._states.once=new J4(A,this.getTz()):this._states.pattern=new r82(A,this.options.timezone,{mode:this.options.mode,alternativeWeekdays:this.options.alternativeWeekdays,sloppyRanges:this.options.sloppyRanges}),this.name){if(CH0.find((X)=>X.name===this.name))throw Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");CH0.push(this)}return B!==void 0&&FOw(B)&&(this.fn=B,this.schedule()),this}nextRun(A){let Q=this._next(A);return Q?this.applyDayOffset(Q.getDate(!1)):null}nextRuns(A,Q){this._states.maxRuns!==void 0&&A>this._states.maxRuns&&(A=this._states.maxRuns);let w=Q||this._states.currentRun||void 0;return this._enumerateRuns(A,w,"next")}previousRuns(A,Q){return this._enumerateRuns(A,Q||void 0,"previous")}_enumerateRuns(A,Q,w){let $=[],B=Q?new J4(Q,this.getTz()):null,X=w==="next"?this._next:this._previous;for(;A--;){let Y=X.call(this,B);if(!Y)break;let Z=Y.getDate(!1);$.push(this.applyDayOffset(Z)),B=Y}return $}match(A){if(this._states.once){let w=new J4(A,this.getTz());w.ms=0;let $=new J4(this._states.once,this.getTz());return $.ms=0,w.getTime()===$.getTime()}let Q=new J4(A,this.getTz());return Q.ms=0,Q.match(this._states.pattern,this.options)}getPattern(){if(!this._states.once)return this._states.pattern?this._states.pattern.pattern:void 0}getOnce(){return this._states.once?this._states.once.getDate():null}isRunning(){let A=this.nextRun(this._states.currentRun),Q=!this._states.paused,w=this.fn!==void 0,$=!this._states.kill;return Q&&w&&$&&A!==null}isStopped(){return this._states.kill}isBusy(){return this._states.blocking}currentRun(){return this._states.currentRun?this._states.currentRun.getDate():null}previousRun(){return this._states.previousRun?this._states.previousRun.getDate():null}msToNext(A){let Q=this._next(A);return Q?A instanceof J4||A instanceof Date?Q.getTime()-A.getTime():Q.getTime()-new J4(A).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let A=CH0.indexOf(this);A>=0&&CH0.splice(A,1)}pause(){return this._states.paused=!0,!this._states.kill}resume(){return this._states.paused=!1,!this._states.kill}schedule(A){if(A&&this.fn)throw Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");A&&(this.fn=A);let Q=this.msToNext(),w=this.nextRun(this._states.currentRun);return Q==null||isNaN(Q)||w===null?this:(Q>o82&&(Q=o82),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(w),Q),this._states.currentTimeout&&this.options.unref&&IOw(this._states.currentTimeout),this)}async _trigger(A){this._states.blocking=!0,this._states.currentRun=new J4(void 0,this.getTz());try{if(this.options.catch)try{this.fn!==void 0&&await this.fn(this,this.options.context)}catch(Q){if(Ua(this.options.catch))try{this.options.catch(Q,this)}catch{}}else this.fn!==void 0&&await this.fn(this,this.options.context)}finally{this._states.previousRun=new J4(A,this.getTz()),this._states.blocking=!1}}async trigger(){await this._trigger()}runsLeft(){return this._states.maxRuns}_checkTrigger(A){let Q=new Date,w=!this._states.paused&&Q.getTime()>=A.getTime(),$=this._states.blocking&&this.options.protect;w&&!$?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):w&&$&&Ua(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()}_next(A){let Q=!!(A||this._states.currentRun),w=!1;!A&&this.options.startAt&&this.options.interval&&([A,Q]=this._calculatePreviousRun(A,Q),w=!A),A=new J4(A,this.getTz()),this.options.startAt&&A&&A.getTime()<this.options.startAt.getTime()&&(A=this.options.startAt);let $=this._states.once||new J4(A,this.getTz());return!w&&$!==this._states.once&&($=$.increment(this._states.pattern,this.options,Q)),this._states.once&&this._states.once.getTime()<=A.getTime()||$===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&$.getTime()>=this.options.stopAt.getTime()?null:$}_previous(A){let Q=new J4(A,this.getTz());this.options.stopAt&&Q.getTime()>this.options.stopAt.getTime()&&(Q=this.options.stopAt);let w=new J4(Q,this.getTz());return this._states.once?this._states.once.getTime()<Q.getTime()?this._states.once:null:(w=w.decrement(this._states.pattern,this.options),w===null||this.options.startAt&&w.getTime()<this.options.startAt.getTime()?null:w)}_calculatePreviousRun(A,Q){let w=new J4(void 0,this.getTz()),$=A;if(this.options.startAt.getTime()<=w.getTime()){$=this.options.startAt;let B=$.getTime()+this.options.interval*1000;for(;B<=w.getTime();)$=new J4($,this.getTz()).increment(this._states.pattern,this.options,!0),B=$.getTime()+this.options.interval*1000;Q=!0}return $===null&&($=void 0),[$,Q]}};class yH0{scheduleCron(A,Q){let w=new P0A(A,()=>{Q()});return{stop:()=>w.stop()}}scheduleInterval(A,Q){let w=setInterval(()=>{Q()},A);return{stop:()=>clearInterval(w)}}validateCron(A){new P0A(A).stop()}}C0();var t82=f.union([f.string().min(1),f.object({location:f.enum(["metadata","frontmatter"]),field:f.string().min(1)})]),gH0=f.object({entityType:f.string().min(1),attachmentType:f.string().min(1),mediaEntityType:f.enum(["image","document"]),targetEntityField:t82.optional(),requiredWhen:f.object({status:f.string().min(1).optional(),visibility:f.string().min(1).optional()}).optional(),autoGenerate:f.boolean().optional(),requiredForPublish:f.boolean().optional(),jobType:f.string().min(1).optional()});function M0A(A){return`${A.entityType}:${A.attachmentType}`}class dq{static instance=null;definitions=new Map;static getInstance(){return dq.instance??=new dq,dq.instance}static resetInstance(){dq.instance=null}static createFresh(){return new dq}constructor(){}register(A){let Q=gH0.parse(A),w=M0A(Q);return this.definitions.set(w,Q),()=>this.unregister(Q.entityType,Q.attachmentType)}get(A,Q){return this.definitions.get(M0A({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(M0A({entityType:A,attachmentType:Q}))}clear(){this.definitions.clear()}}K7();k2();class EH0{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 O0A(A.metadata[Q]);if(Q.location==="metadata")return O0A(A.metadata[Q.field]);let{frontmatter:w}=p6(A.content);return O0A(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 q1(`${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 O0A(A){return typeof A==="string"?A.length>0:A!==void 0}fA();C0();var bOw=f.object({id:f.string().min(1)});async function AB2(A,Q){let{bodyContent:w,coverImageId:$,documents:B,sourceEntityType:X,sourceEntityId:Y}=LOw(Q.content),Z=$?await NOw(A,$):void 0,H;if(B&&B.length>0){let K=await jOw(A,B);if(K.length>0)H=K}H??=await _Ow(A,X,Y);let W={bodyContent:w};if(Z)W.imageData=Z;if(H&&H.length>0)W.documentData=H;return W}function LOw(A){try{let Q=BQ(A,f.record(f.string(),f.unknown())),w=Q.metadata.coverImageId,$=typeof w==="string"?w:void 0,B=kOw(Q.metadata.documents),X=e82(Q.metadata.sourceEntityType),Y=e82(Q.metadata.sourceEntityId);return{bodyContent:Q.content,...$&&{coverImageId:$},...B.length>0&&{documents:B},...X&&{sourceEntityType:X},...Y&&{sourceEntityId:Y}}}catch{return{bodyContent:A}}}function kOw(A){if(!Array.isArray(A))return[];return A.flatMap((Q)=>{let w=bOw.safeParse(Q);return w.success?[w.data]:[]})}function e82(A){return typeof A==="string"&&A.length>0?A:void 0}async function _Ow(A,Q,w){if(!Q||!w)return;let $=await A.attachments.resolve({sourceEntityType:Q,sourceEntityId:w,attachmentType:"carousel"});return $?[$]:void 0}async function NOw(A,Q){let w=await A.entityService.getEntity({entityType:"image",id:Q});if(!w?.content)return;let $=QB2(w.content);if(!$?.mimeType.startsWith("image/"))return;return{data:$.data,mimeType:$.mimeType}}async function jOw(A,Q){return(await Promise.all(Q.map(($)=>POw(A,$)))).filter(($)=>$!==void 0)}async function POw(A,Q){let w=await A.entityService.getEntity({entityType:"document",id:Q.id});if(!w?.content)return;let $=QB2(w.content);if($?.mimeType!=="application/pdf")return;return{type:"document",data:$.data,mimeType:"application/pdf",filename:MOw(w,Q.id)}}function QB2(A){let Q=A.match(/^data:([^;]+);base64,(.+)$/);if(!Q?.[1]||!Q[2])return;return{mimeType:Q[1],data:Buffer.from(Q[2],"base64")}}function MOw(A,Q){let w=A.metadata.filename;return typeof w==="string"&&w.length>0?w:`${Q}.pdf`}K7();var OOw=/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/;async function x0A(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,...xOw(w.id,$.publishResultIdField)},H={...Q,content:wB2(Q.content,Y,w.id,$.publishResultIdField,B),metadata:Z};return await A.entityService.updateEntity({entity:H}),H}function wB2(A,Q,w,$,B="publishedAt"){if(!OOw.test(A))return A;let X=u4(u4(A,"status","published"),B,Q);if(!w||!$)return X;return u4(X,$,w)}function xOw(A,Q){if(!Q||Q==="platformId")return{};return{[Q]:A}}class sE{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 AB2(this.deps.context,w),H=await B.publish(X,w.metadata,Y,Z),W=this.deps.providerRegistry.getPublishResultIdField($),K=this.deps.providerRegistry.getPublishTimestampField($),U=await x0A(this.deps.context,w,H,{...W?{publishResultIdField:W}:{},...K?{publishTimestampField:K}:{}});return await this.runPublishAssetPreflight(U),{entity:U,result:H}}async runPublishAssetPreflight(A){if(!this.deps.publishAssetPreflight)return;try{await this.deps.publishAssetPreflight.ensureForEntity(A)}catch(Q){this.deps.context.logger.warn("Publish asset preflight failed",{entityType:A.entityType,entityId:A.id,error:Q instanceof Error?Q.message:String(Q)})}}async findPublishableEntity(A,Q,w){if(Q)return this.deps.context.entityService.getEntity({entityType:A,id:Q});if(!w)return null;return(await this.deps.context.entityService.listEntities({entityType:A,options:{filter:{metadata:{slug:w}},limit:1}}))[0]??null}}fA();C0();var R0A=f.object({action:f.enum(["list","add","remove","reorder"]).describe("Queue action to perform"),entityType:f.string().optional().describe("Entity type (required for add/remove/reorder, optional for list)"),entityId:f.string().optional().describe("Entity ID (required for add/remove/reorder)"),position:f.number().optional().describe("New position for reorder action (1-based)")}),v0A=f.object({position:f.number(),entityType:f.string(),entityId:f.string(),queuedAt:f.string()}),ROw=f.object({success:f.literal(!0),message:f.string().optional(),data:f.object({queue:f.array(v0A).optional(),entityType:f.string().optional(),entityId:f.string().optional(),position:f.number().optional()}).optional()}),vOw=f.object({success:f.literal(!1),error:f.string(),code:f.string().optional()}),h0A=f.union([ROw,vOw]);function TH0(A,Q,w){return{...i6(Q,"queue","Manage the publish queue for all entity types (list, add, remove, reorder)",R0A,async(B,X)=>{let{action:Y,entityType:Z,entityId:H,position:W}=B;switch(Y){case"list":return hOw(w,Z);case"add":return COw(A,w,Z,H,X);case"remove":return yOw(A,w,Z,H,X);case"reorder":return gOw(A,w,Z,H,W,X);default:return{success:!1,error:`Unknown action: ${Y}`}}},{sideEffects:"writes"}),outputSchema:h0A}}async function hOw(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 COw(A,Q,w,$,B){let X=C0A("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 yOw(A,Q,w,$,B){let X=C0A("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 gOw(A,Q,w,$,B,X){let Y=C0A("reorder",w,$);if(!Y.success)return Y.error;let Z=EOw(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 C0A(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 EOw(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}}C0();import{createHash as TOw}from"crypto";var y0A=f.object({entityType:f.string().describe("Entity type to publish (e.g., social-post, post, deck)"),id:f.string().optional().describe("Entity ID to publish"),slug:f.string().optional().describe("Entity slug to publish"),confirmed:f.boolean().optional(),confirmationToken:f.string().optional(),contentHash:f.string().optional(),expiresAt:f.string().datetime().optional()}),SOw=f.object({entityType:f.string(),id:f.string().optional(),slug:f.string().optional(),confirmed:f.boolean().optional(),confirmationToken:f.string().optional(),contentHash:f.string().optional(),expiresAt:f.string().datetime().optional()}),mOw=f.object({success:f.literal(!0),message:f.string().optional(),data:f.object({entityType:f.string().optional(),entityId:f.string().optional(),platformId:f.string().optional(),url:f.string().optional()}).optional()}),uOw=f.object({success:f.literal(!1),error:f.string(),code:f.string().optional()}),cOw=f.object({success:f.literal(!1).optional(),error:f.string().optional(),needsConfirmation:f.literal(!0),toolName:f.string(),summary:f.string(),preview:f.string().optional(),args:f.unknown()}),g0A=f.union([mOw,uOw,cOw]),lOw=900000;function SH0(A,Q,w,$){let B=$??new sE({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:y0A.shape,outputSchema:g0A,visibility:"anchor",sideEffects:"external",handler:async(Y,Z)=>{let H=SOw.safeParse(Y);if(!H.success)return{success:!1,error:`Invalid input: ${H.error.issues.map((J)=>`${J.path.join(".")}: ${J.message}`).join(", ")}`};let W=H.data,{entityType:K,id:U,slug:G}=W;try{A.permissions.assertEntityActionAllowed(K,"publish",Z)}catch(J){return{success:!1,error:J instanceof Error?J.message:String(J)}}let q=await B.resolveCandidate({entityType:K,id:U,slug:G});if("error"in q)return{success:!1,error:q.error};let{entity:V}=q;if(W.confirmed){let J=iOw(X,W,V);if(J!==null)return J;let F;try{F=await B.publish({entityType:K,id:V.id})}catch(_){return{success:!1,error:_ instanceof Error?_.message:String(_)}}if("error"in F)return{success:!1,error:F.error};let{entity:k,result:j}=F;return{success:!0,data:{entityType:K,entityId:k.id,platformId:j.id,url:j.url},message:`Published ${K}:${k.id}`}}return pOw(X,W,V)}}}function pOw(A,Q,w){let $=new Date(Date.now()+lOw).toISOString(),B=$B2(A,w,$),X=dOw(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 iOw(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($!==$B2(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 $B2(A,Q,w){return TOw("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 dOw(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}fA();C0();var E0A=f.object({entityType:f.string().min(1).describe("Entity type to reconcile"),status:f.string().min(1).optional().describe("Optional metadata status filter, e.g. published"),assetType:f.string().min(1).optional().describe("Optional attachment type filter, e.g. og-image")}),T0A=f.object({success:f.literal(!0),data:f.object({entityType:f.string(),assetType:f.string().optional(),checkedEntities:f.number(),checkedAssets:f.number(),enqueued:f.number(),skipped:f.number()}),message:f.string().optional()});function mH0(A,Q,w,$){return{...i6(Q,"ensure-assets","Reconcile configured publish assets for existing entities, queueing missing generated assets such as OG images.",E0A,async(X,Y)=>{if(A.permissions.assertEntityActionAllowed(X.entityType,"publish",Y),w.list(X.entityType).filter((G)=>G.autoGenerate===!0).filter((G)=>!X.assetType||G.attachmentType===X.assetType).length===0)return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:0,checkedAssets:0,enqueued:0,skipped:0},message:`No publish assets configured for ${X.entityType}`};let H=await A.entityService.listEntities({entityType:X.entityType,options:{...X.status&&{filter:{metadata:{status:X.status}}}}}),W=0,K=0,U=0;for(let G of H){let q=await $.ensureForEntity(G,{...X.assetType&&{attachmentType:X.assetType}});W+=q.checked,K+=q.enqueued,U+=q.skipped}return{success:!0,data:{entityType:X.entityType,...X.assetType&&{assetType:X.assetType},checkedEntities:H.length,checkedAssets:W,enqueued:K,skipped:U},message:`Queued ${K} publish asset job(s)`}},{sideEffects:"writes"}),outputSchema:T0A}}fA();function BB2(A,Q){nOw(A,Q),rOw(A,Q),oOw(A,Q),sOw(A,Q)}function nOw(A,Q){A.messaging.subscribe(_Y.REGISTER,async(w)=>aOw(Q,w.payload)),A.messaging.subscribe(_Y.QUEUE,async(w)=>Qxw(A,Q,w.payload)),A.messaging.subscribe(_Y.DIRECT,async(w)=>wxw(A,Q,w.payload)),A.messaging.subscribe(_Y.REMOVE,async(w)=>$xw(Q,w.payload)),A.messaging.subscribe(_Y.REORDER,async(w)=>Bxw(Q,w.payload)),A.messaging.subscribe(_Y.LIST,async(w)=>Xxw(A,Q,w.payload)),A.messaging.subscribe(_Y.REPORT_SUCCESS,async(w)=>Yxw(Q,w.payload)),A.messaging.subscribe(_Y.REPORT_FAILURE,async(w)=>Zxw(Q,w.payload)),Q.logger.debug("Subscribed to publish messages")}function rOw(A,Q){A.messaging.subscribe(CL.REPORT_SUCCESS,async(w)=>fxw(Q,w.payload)),A.messaging.subscribe(CL.REPORT_FAILURE,async(w)=>Hxw(Q,w.payload)),Q.logger.debug("Subscribed to generation messages")}function oOw(A,Q){A.messaging.subscribe(S82.REGISTER,async(w)=>tOw(Q,w.payload)),Q.logger.debug("Subscribed to publish asset messages")}function sOw(A,Q){let w=async($)=>eOw(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 aOw(A,Q){let{entityType:w,provider:$,config:B}=Q;try{let X=B?m82.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=dA(X);return A.logger.error(`Failed to register provider: ${Y}`),{success:!1}}}async function tOw(A,Q){let w=gH0.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 eOw(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(!Axw($))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:dA($)}),{success:!1}}}function Axw(A){if(!A)return!1;let Q=T82.safeParse(A.metadata);return Q.success&&Q.data.status==="published"}async function Qxw(A,Q,w){let{entityType:$,entityId:B}=w;try{let X=w.authContext??Ha;A.permissions.assertEntityActionAllowed($,"publish",X);let Y=await Q.queueManager.add($,B,X);return await A.messaging.send({type:_Y.QUEUED,payload:{entityType:$,entityId:B,position:Y.position}}),Q.logger.debug(`Entity queued: ${B}`,{entityType:$,position:Y.position}),{success:!0}}catch(X){let Y=dA(X);return Q.logger.error(`Failed to queue entity: ${Y}`),{success:!1}}}async function wxw(A,Q,w){let{entityType:$,entityId:B}=w,X=w.authContext??Ha;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=dA(Y);return Q.logger.error(`Failed direct publish request: ${Z}`),{success:!1}}}async function $xw(A,Q){let{entityType:w,entityId:$}=Q;try{return await A.queueManager.remove(w,$),A.logger.debug(`Entity removed from queue: ${$}`,{entityType:w}),{success:!0}}catch(B){let X=dA(B);return A.logger.error(`Failed to remove entity: ${X}`),{success:!1}}}async function Bxw(A,Q){let{entityType:w,entityId:$,position:B}=Q;try{return await A.queueManager.reorder(w,$,B),A.logger.debug(`Entity reordered: ${$}`,{entityType:w,newPosition:B}),{success:!0}}catch(X){let Y=dA(X);return A.logger.error(`Failed to reorder entity: ${Y}`),{success:!1}}}async function Xxw(A,Q,w){let{entityType:$}=w;try{let B=await Q.queueManager.list($);return await A.messaging.send({type:_Y.LIST_RESPONSE,payload:{entityType:$,queue:B.map((X)=>({entityId:X.entityId,position:X.position,queuedAt:X.queuedAt}))}}),{success:!0}}catch(B){let X=dA(B);return Q.logger.error(`Failed to list queue: ${X}`),{success:!1}}}async function Yxw(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 Zxw(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 fxw(A,Q){let{entityType:w,entityId:$}=Q;return A.scheduler.completeGeneration(w,$),A.logger.info("Generation completed",{entityType:w,entityId:$}),{success:!0}}async function Hxw(A,Q){let{entityType:w,error:$}=Q;return A.scheduler.failGeneration(w,$),A.logger.warn("Generation failed",{entityType:w,error:$}),{success:!0}}async function XB2(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:dA(B)}),{shouldGenerate:!1,reason:`Condition check failed: ${dA(B)}`}}}function YB2(A){let{context:Q,config:w,queueManager:$,providerRegistry:B,retryTracker:X,publishExecutor:Y,logger:Z}=A,H=Wxw(Q);return zG.createFresh({queueManager:$,providerRegistry:B,retryTracker:X,logger:Z,backend:new yH0,...w.entitySchedules&&{entitySchedules:w.entitySchedules},...w.generationSchedules&&{generationSchedules:w.generationSchedules},...w.generationConditions&&{generationConditions:w.generationConditions},messageBus:H,publishExecutor:Y,onCheckGenerationConditions:(W,K)=>XB2(Q.entityService,Z,W,K)})}function Wxw(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:()=>{}}}async function ZB2(A,Q,w){let $=A.getEntityTypes();for(let X of $){let Y=await A.listEntities({entityType:X,options:{filter:{metadata:{status:"queued"}}}});for(let Z of Y)await Q.add(Z.entityType,Z.id)}let B=0;for(let X of $){let Y=await Q.list(X);B+=Y.length}if(B>0)w.info(`Rebuilt queue with ${B} queued entities`)}C0();var Kxw=["draft","queued","published","failed"];async function fB2(A,Q){await A.messaging.send({type:"dashboard:register-widget",payload:{id:"publication-pipeline",pluginId:Q,title:"Publication Pipeline",group:"publishing",section:"secondary",priority:100,rendererName:"PipelineWidget",visibility:"anchor",dataProvider:()=>zxw(A),digestProvider:Gxw}})}var Uxw=f.object({summary:f.object({draft:f.number(),queued:f.number(),published:f.number(),failed:f.number()}),generating:f.array(f.unknown())});function Gxw(A){let{summary:Q,generating:w}=Uxw.parse(A),$=Q.queued+w.length,B=$===0?"idle":`${Q.queued} queued \xB7 ${w.length} generating`,X=Q.failed>0?`${Q.draft} drafts \xB7 ${Q.failed} failed`:`${Q.draft} drafts`,Y=Q.draft+Q.failed;return{digest:[{label:"Pipeline",value:B,...$>0?{tone:"warn"}:{}},{label:"Awaiting review",value:X,...Y>0?{tone:"warn"}:{}},{label:"Published",value:String(Q.published),tone:"good"}],needsOperator:Y}}var Dxw=f.object({sourceEntityType:f.string(),sourceEntityId:f.string(),attachmentType:f.string().optional()});async function qxw(A){let Q=await A.jobs.getActiveJobs(),w=[];for(let $ of Q){if($.source!=="content-pipeline")continue;if($.status!=="pending"&&$.status!=="processing")continue;let B;try{B=JSON.parse($.data)}catch{continue}let X=Dxw.safeParse(B);if(!X.success)continue;w.push({id:$.id,label:X.data.attachmentType??$.type,target:`${X.data.sourceEntityType}/${X.data.sourceEntityId}`,status:$.status})}return w}async function zxw(A){let Q=A.entityService.getEntityTypes(),w=[],$={draft:0,queued:0,published:0,failed:0};for(let B of Q){let X=await A.entityService.listEntities({entityType:B});for(let Y of X){let Z=Vxw(Y.metadata.status);if(!Z)continue;$[Z]++,w.push({id:Y.id,title:Jxw(Y.id,Y.metadata.title),type:B,status:Z})}}return{summary:$,items:w,generating:await qxw(A)}}function Vxw(A){return Kxw.find((Q)=>Q===A)}function Jxw(A,Q){return typeof Q==="string"?Q:A}var HB2={name:"@brains/content-pipeline",version:"0.2.0-alpha.169",description:"Content pipeline plugin for managing entity publishing queues, scheduling, and generation",dependencies:{"@brains/contracts":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*",croner:"^10.0.1"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14",typescript:"^7.0.2"},exports:{".":{types:"./src/index.ts",default:"./src/index.ts"}},files:["src"],main:"src/index.ts",private:!0,scripts:{lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"src/index.ts"};class S0A extends Uw{pluginContext;queueManager;providerRegistry;retryTracker;publishExecutor;publishAssetRegistry;publishAssetPreflight;scheduler;constructor(A={}){super("content-pipeline",HB2,A,u82)}async onRegister(A){this.pluginContext=A,this.queueManager=lq.createFresh(),this.providerRegistry=pq.createFresh(),this.retryTracker=iq.createFresh(),this.publishAssetRegistry=dq.createFresh(),this.publishAssetPreflight=new EH0({context:A,registry:this.publishAssetRegistry}),this.publishExecutor=new sE({context:A,providerRegistry:this.providerRegistry,publishAssetPreflight:this.publishAssetPreflight}),this.scheduler=YB2({context:A,config:this.config,queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,logger:this.logger}),BB2(A,{queueManager:this.queueManager,providerRegistry:this.providerRegistry,retryTracker:this.retryTracker,publishExecutor:this.publishExecutor,publishAssetRegistry:this.publishAssetRegistry,publishAssetPreflight:this.publishAssetPreflight,scheduler:this.scheduler,logger:this.logger})}async onReady(A){await ZB2(A.entityService,this.queueManager,this.logger),await fB2(A,this.id),await this.scheduler.start(),this.logger.info("Content pipeline plugin started")}async getTools(){if(!this.pluginContext)throw Error("Plugin context not initialized");return[TH0(this.pluginContext,this.id,this.queueManager),SH0(this.pluginContext,this.id,this.providerRegistry,this.publishExecutor),mH0(this.pluginContext,this.id,this.publishAssetRegistry,this.publishAssetPreflight)]}async getInstructions(){return'## Publishing\n- Use `content-pipeline_queue` to manage the publish queue \u2014 list queued items, add entities to the queue, remove them, or reorder.\n- Use `content-pipeline_publish` to publish an entity directly to its platform (e.g. LinkedIn, Buttondown). This tool has its own confirmation flow; call it without `confirmed` when the user asks to publish instead of asking for plain-text confirmation. Follow-up requests like "publish it now" should target the entity just read, generated, or updated in the conversation, including a post just changed to draft.\n- Use `content-pipeline_ensure-assets` to reconcile missing publish assets such as generated OG images for already-published content.\n- When users ask about their "publish queue", "publishing queue", or "what\'s queued", use `content-pipeline_queue`.'}getQueueManager(){return this.queueManager}getProviderRegistry(){return this.providerRegistry}getRetryTracker(){return this.retryTracker}getPublishAssetRegistry(){return this.publishAssetRegistry}getScheduler(){return this.scheduler}async onShutdown(){await this.scheduler.stop(),lq.resetInstance(),pq.resetInstance(),iq.resetInstance(),dq.resetInstance()}}function m0A(A={}){return new S0A(A)}fA();C0();var WB2=f.object({accountId:f.string().describe("Cloudflare account ID"),apiToken:f.string().describe("Cloudflare API token with Analytics:Read permission"),siteTag:f.string().describe("Cloudflare Web Analytics site tag")}),u0A=f.object({cloudflare:WB2.optional()});fA();C0();var Ixw=f.object({date:f.string().describe("Single date in YYYY-MM-DD format").optional(),days:f.number().min(1).max(365).describe("Number of days back from yesterday (e.g., 7 for last week)").optional(),startDate:f.string().describe("Start date in YYYY-MM-DD format (use with endDate)").optional(),endDate:f.string().describe("End date in YYYY-MM-DD format (use with startDate)").optional(),limit:f.number().min(1).max(100).default(20).describe("Maximum items for breakdowns (pages, referrers, countries)")});function bxw(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 KB2(A,Q,w){let $=[];if(!w)return $;return $.push(i6(A,"query",`Query website analytics from Cloudflare.
|
|
7974
7974
|
|
|
7975
7975
|
Date range options (use only one):
|
|
7976
7976
|
- No params: yesterday only
|
|
@@ -8108,7 +8108,7 @@ Returns pageviews, visitors, top pages, referrers, devices, and countries.`,Ixw,
|
|
|
8108
8108
|
}
|
|
8109
8109
|
}
|
|
8110
8110
|
}
|
|
8111
|
-
`,{...this.baseVariables(A),limit:A.limit??20})).map(($)=>({country:$.dimensions.countryName,visits:$.sum.visits}))}}var l0A=7,Lxw=10;function GB2(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=L$0(),w=ygA(l0A),$=Wh(w),B=Wh(Q);try{let[X,Y]=await Promise.all([A.getWebsiteStats({startDate:$,endDate:B}),A.getTopPages({startDate:$,endDate:B,limit:Lxw})]);return{days:l0A,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:l0A}}}}var DB2={name:"@brains/analytics",version:"0.2.0-alpha.
|
|
8111
|
+
`,{...this.baseVariables(A),limit:A.limit??20})).map(($)=>({country:$.dimensions.countryName,visits:$.sum.visits}))}}var l0A=7,Lxw=10;function GB2(A){return async()=>{if(!A)return{unavailable:!0,reason:"Cloudflare analytics not configured"};let Q=L$0(),w=ygA(l0A),$=Wh(w),B=Wh(Q);try{let[X,Y]=await Promise.all([A.getWebsiteStats({startDate:$,endDate:B}),A.getTopPages({startDate:$,endDate:B,limit:Lxw})]);return{days:l0A,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:l0A}}}}var DB2={name:"@brains/analytics",version:"0.2.0-alpha.169",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 qB2 extends Uw{cloudflareClient;constructor(A={}){super("analytics",DB2,A,u0A)}async onRegister(A){this.cloudflareClient=this.config.cloudflare?new c0A(this.config.cloudflare):void 0,A.insights.register("traffic-overview",GB2(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:UB2(Q)}})}async getTools(){return KB2(this.id,this.getContext(),this.cloudflareClient)}}function _xw(A={}){return new qB2(A)}var uH0=_xw;fA();C0();fA();C0();import{join as hxw}from"path";k2();var zB2="note",Nxw=new Set(["description","excerpt","summary","tagline","story"]);function jxw(A){if(A.endsWith("s"))return A;return mK(A)}function qa(A){return A===zB2}function VB2(A,Q){let w=A===zB2?"Note":FF(A),$=Q?.label??w;return{label:$,pluralLabel:Q?.pluralName??jxw($)}}function Ga(A){return typeof A==="object"&&A!==null}function _M(A){if(!Ga(A))return;let Q=A.def;return Ga(Q)?Q:void 0}function JB2(A){let Q=_M(A)?.type;return typeof Q==="string"?Q:void 0}function Pxw(A){return typeof A==="function"?A():A}function p0A(A,Q=!1,w){let $=JB2(A),B=_M(A);if($==="optional"||$==="nullable")return p0A(B?.innerType,!0,w);if($==="default")return p0A(B?.innerType,!0,Pxw(B?.defaultValue));let X={inner:A,isOptional:Q};if(w!==void 0)X.defaultValue=w;return X}function Mxw(A){let Q=_M(A)?.entries;if(!Ga(Q))return;let w=Object.values(Q);return w.every(($)=>typeof $==="string")?w:void 0}function Oxw(A){let Q=_M(A)?.values;return Array.isArray(Q)?Q[0]:void 0}function xxw(A){let Q=_M(A)?.checks;if(!Array.isArray(Q))return!1;return Q.some((w)=>{return _M(w)?.format==="datetime"})}function Rxw(A){return A==="imageId"||A.endsWith("ImageId")}function vxw(A){if(!Ga(A))return;let Q=A.shape;return Ga(Q)?Q:void 0}function Da(A,Q){let{inner:w,isOptional:$,defaultValue:B}=p0A(Q),X=JB2(w),Y=B??Oxw(w),Z={name:A,label:FF(A),widget:"string",...$&&{required:!1},...Y!==void 0&&{default:Y}};switch(X){case"string":{if(Rxw(A))return{...Z,widget:"image"};if(xxw(w))return{...Z,widget:"datetime"};if(Nxw.has(A))return{...Z,widget:"text"};return{...Z,widget:"string"}}case"number":return{...Z,widget:"number"};case"boolean":return{...Z,widget:"boolean"};case"enum":{let H=Mxw(w);return{...Z,widget:"select",...H?{options:H}:{}}}case"array":{let H=_M(w)?.element,W=Da("item",H);if(W.widget==="object"&&W.fields)return{...Z,widget:"list",fields:W.fields};return{...Z,widget:"list",field:{name:A,label:FF(A),widget:W.widget}}}case"object":{let H=Object.entries(vxw(w)??{}).map(([W,K])=>Da(W,K));return{...Z,widget:"object",fields:H}}case"literal":return{...Z,widget:"string"};default:return{...Z,widget:"string"}}}function FB2(A){return`<!doctype html>
|
|
8112
8112
|
<html lang="en" data-climate="paper">
|
|
8113
8113
|
<head>
|
|
8114
8114
|
<meta charset="utf-8" />
|
|
@@ -8166,7 +8166,7 @@ ${ty}
|
|
|
8166
8166
|
</html>`}var Cxw=hxw(import.meta.dir,"..","dist","ui","cms-app.js"),yxw=f.object({entityType:f.string(),id:f.string(),frontmatter:f.record(f.string(),f.unknown()),body:f.string().optional(),baseContentHash:f.string().optional()}),gxw=f.object({entityType:f.string(),frontmatter:f.record(f.string(),f.unknown()),body:f.string().optional()}),i0A={entityType:f.string(),body:f.string(),frontmatter:f.record(f.string(),f.unknown())},Exw=f.union([f.object({...i0A,variant:f.literal("rewrite").optional(),instruction:f.string().trim().min(1),selection:f.string().min(1).max(8000)}),f.object({...i0A,variant:f.literal("summarise"),targetField:f.string().trim().min(1),body:f.string().min(1)}),f.object({...i0A,variant:f.literal("tag-suggest"),targetField:f.string().trim().min(1),body:f.string().min(1)})]),IB2=f.object({suggestion:f.string()}),Txw=f.object({suggestions:f.array(f.string().trim().min(1)).max(12)}),Sxw=f.object({selection:f.string().min(1).max(8000),instruction:f.string().trim().min(1).max(2000),agent:f.string().trim().min(1).max(253)}),mxw=f.looseObject({response:f.string()}),uxw=f.object({agents:f.array(f.object({id:f.string(),label:f.string()}))}),cxw="file",bB2=10485760,lxw=f.object({watchEnabled:f.boolean(),lastSync:f.string().nullable(),git:f.object({branch:f.string(),hasChanges:f.boolean(),ahead:f.number(),behind:f.number(),lastCommit:f.string().nullable(),remote:f.string().nullable()}).nullable()});function LB2(A){let{routePath:Q,getContext:w,resolveOperatorSession:$,getEntityDisplay:B}=A,X=`${Q}/assets/app.js`,Y=(H)=>`${Q}/api/${H}`,Z=async(H)=>await $(H)?null:CQ({error:"Operator session required"},401);return[{path:Q,method:"GET",public:!0,handler:async(H)=>{if(!await $(H))return new Response(null,{status:302,headers:{Location:`/login?return_to=${encodeURIComponent(Q)}`,"Cache-Control":"no-store"}});return new Response(FB2({assetPath:X,surfaces:lb(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:X,method:"GET",public:!0,handler:async()=>{let H=Bun.file(Cxw);if(!await H.exists())return new Response("CMS editor UI asset not built",{status:404});return new Response(H,{headers:{"Content-Type":"text/javascript; charset=utf-8","Cache-Control":"no-cache"}})}},{path:Y("types"),method:"GET",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return ixw(w(),B())}},{path:Y("schema"),method:"GET",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return dxw(w(),H)}},{path:Y("entities"),method:"GET",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return nxw(w(),H)}},{path:Y("entities"),method:"PUT",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return rxw(w(),H)}},{path:Y("entities"),method:"POST",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return oxw(w(),H)}},{path:Y("entities"),method:"DELETE",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return sxw(w(),H)}},{path:Y("upload"),method:"POST",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return ARw(w(),H,Y("upload"))}},{path:Y("assist"),method:"POST",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return axw(w(),H)}},{path:Y("agents"),method:"GET",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return txw(w())}},{path:Y("ask-agent"),method:"POST",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return exw(w(),H)}},{path:Y("sync-status"),method:"GET",public:!0,handler:async(H)=>{let W=await Z(H);if(W)return W;return pxw(w())}}]}async function pxw(A){let Q={directorySync:null,git:null},w=await A.messaging.send({type:"sync:status:request",payload:{}});if(!("success"in w)||!w.success)return CQ(Q);let $=lxw.safeParse(w.data);if(!$.success)return CQ(Q);return CQ({directorySync:{lastSync:$.data.lastSync,watching:$.data.watchEnabled},git:$.data.git})}async function ixw(A,Q){let w=new Map((await A.entityService.getEntityCounts()).map((B)=>[B.entityType,B.count])),$=A.entityService.getEntityTypes().flatMap((B)=>{if(!A.entities.getEffectiveFrontmatterSchema(B))return[];let Y=A.entities.getAdapter(B);return[{entityType:B,label:VB2(B,Q?.[B]).pluralLabel,isSingleton:Y?.isSingleton===!0,hasBody:Y?.hasBody!==!1,count:w.get(B)??0}]});return CQ({types:$})}function dxw(A,Q){let w=new URL(Q.url).searchParams.get("type");if(!w)return CQ({error:"type query parameter is required"},400);let $=A.entities.getEffectiveFrontmatterSchema(w);if(!$)return CQ({error:`Unknown entity type: ${w}`},404);let B=A.entities.getAdapter(w),X=qa(w),Y=X?[]:Object.entries($.shape).map(([Z,H])=>Da(Z,H));return CQ({entityType:w,format:X?"raw":"frontmatter",isSingleton:B?.isSingleton===!0,hasBody:X||B?.hasBody!==!1,fields:Y})}async function nxw(A,Q){let w=new URL(Q.url).searchParams,$=w.get("type");if(!$)return CQ({error:"type query parameter is required"},400);if(!A.entities.getEffectiveFrontmatterSchema($))return CQ({error:`Unknown entity type: ${$}`},404);let B=w.get("id");if(B){let Y=await A.entityService.getEntity({entityType:$,id:B});if(!Y)return CQ({error:`Entity not found: ${B}`},404);let{frontmatter:Z,body:H}=d0A($,Y.content);return CQ({entity:{id:Y.id,entityType:Y.entityType,frontmatter:Z,body:H,contentHash:Y.contentHash,created:Y.created,updated:Y.updated}})}let X=await A.entityService.listEntities({entityType:$});return CQ({entities:X.map((Y)=>({id:Y.id,entityType:Y.entityType,frontmatter:d0A($,Y.content).frontmatter,updated:Y.updated}))})}async function rxw(A,Q){let w;try{w=yxw.parse(await Q.json())}catch{return CQ({error:"Invalid update payload"},400)}let{entityType:$,id:B}=w,X=A.entities.getEffectiveFrontmatterSchema($);if(!X)return CQ({error:`Unknown entity type: ${$}`},404);let Y=kB2(A,$,w.body);if(Y)return Y;let Z=qa($);if(Z&&Object.keys(w.frontmatter).length>0)return CQ({error:`Entity type ${$} is raw markdown without frontmatter`},400);let H=Z?{success:!0,data:{}}:X.safeParse(w.frontmatter);if(!H.success)return CQ({error:"Invalid frontmatter",issues:H.error.issues},400);let W=await A.entityService.getEntity({entityType:$,id:B});if(!W)return CQ({error:`Entity not found: ${B}`},404);if(w.baseContentHash!==void 0&&w.baseContentHash!==W.contentHash)return CQ({error:"This entry changed since it was opened \u2014 likely updated by "+"another writer (an agent, or a git import via directory-sync). Reload to review before saving again.",currentContentHash:W.contentHash},409);let K=w.body??d0A($,W.content).body,U=Z?K:l5(K,H.data),G=A.entities.getAdapter($)?.fromMarkdown(U),q={...W,...G,id:W.id,entityType:W.entityType,content:U},V=await A.entityService.updateEntity({entity:q});return CQ({entityId:V.entityId,jobId:V.jobId,skipped:V.skipped})}async function oxw(A,Q){let w;try{w=gxw.parse(await Q.json())}catch{return CQ({error:"Invalid create payload"},400)}let{entityType:$}=w,B=A.entities.getEffectiveFrontmatterSchema($);if(!B)return CQ({error:`Unknown entity type: ${$}`},404);let X=kB2(A,$,w.body);if(X)return X;let Y=qa($);if(Y&&Object.keys(w.frontmatter).length>0)return CQ({error:`Entity type ${$} is raw markdown without frontmatter`},400);let Z=Y?{success:!0,data:{}}:B.safeParse(w.frontmatter);if(!Z.success)return CQ({error:"Invalid frontmatter",issues:Z.error.issues},400);let H=Y?w.body??"":l5(w.body??"",Z.data),W=A.entities.getAdapter($)?.fromMarkdown(H),K=await A.entityService.createEntity({entity:{...W,entityType:$,content:H,metadata:W?.metadata??{}}});return CQ({entityId:K.entityId,jobId:K.jobId},201)}async function sxw(A,Q){let w=new URL(Q.url).searchParams,$=w.get("type"),B=w.get("id");if(!$||!B)return CQ({error:"type and id query parameters are required"},400);if(!await A.entityService.getEntity({entityType:$,id:B}))return CQ({error:`Entity not found: ${B}`},404);let Y=await A.entityService.deleteEntity({entityType:$,id:B});return CQ({deleted:Y})}async function axw(A,Q){let w;try{w=Exw.parse(await Q.json())}catch{return CQ({error:"Invalid assist payload or selection length"},400)}let $=A.entities.getEffectiveFrontmatterSchema(w.entityType);if(!$)return CQ({error:`Unknown entity type: ${w.entityType}`},404);if(w.variant==="summarise"||w.variant==="tag-suggest"){let Y=$.shape[w.targetField];if(!Y)return CQ({error:`Unknown frontmatter field: ${w.targetField}`},400);let Z=Da(w.targetField,Y);if(!(w.variant==="summarise"?Z.widget==="string"||Z.widget==="text":Z.widget==="list"&&Z.field?.widget==="string"))return CQ({error:`Field ${w.targetField} is incompatible with ${w.variant}`},400);let W=["You are editing CMS frontmatter from an existing markdown body.",`Entity type: ${w.entityType}`,`Target field: ${w.targetField}`,`Existing frontmatter JSON: ${JSON.stringify(w.frontmatter)}`,"","Full markdown body:",w.body];if(w.variant==="summarise"){let{object:U}=await A.ai.generateObject(["Summarise the body for the target frontmatter field.","Return only the field value in the suggestion field.",...W].join(`
|
|
8167
8167
|
`),IB2);return CQ({variant:w.variant,targetField:w.targetField,suggestion:U.suggestion})}let{object:K}=await A.ai.generateObject(["Suggest tags for the target frontmatter field.","Return concise tag strings in the suggestions field without duplicates.",...W].join(`
|
|
8168
8168
|
`),Txw);return CQ({variant:w.variant,targetField:w.targetField,suggestions:[...new Set(K.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(`
|
|
8169
|
-
`),{object:X}=await A.ai.generateObject(B,IB2);return CQ({suggestion:X.suggestion})}async function txw(A){let Q=await A.messaging.send({type:"a2a:call:agents",payload:{}});if(!("success"in Q)||!Q.success)return CQ({agents:[]});let w=uxw.safeParse(Q.data);return CQ(w.success?w.data:{agents:[]})}async function exw(A,Q){let w;try{w=Sxw.parse(await Q.json())}catch{return CQ({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 CQ({error:Y?"Agent asking is unavailable":X},Y?503:400)}if($.data===void 0)return CQ({error:"Agent asking is unavailable"},503);let B=mxw.safeParse($.data);if(!B.success)return CQ({error:"Invalid response from agent"},502);return CQ({agentId:w.agent,response:B.data.response})}async function ARw(A,Q,w){let $=Number(Q.headers.get("content-length"));if(Number.isFinite($)&&$>bB2)return CQ({error:"Upload too large"},400);let B;try{B=await Q.formData()}catch{return CQ({error:"Invalid multipart upload"},400)}let X=B.get(cxw);if(!(X instanceof File))return CQ({error:"Missing upload file"},400);if(X.size>bB2)return CQ({error:"Upload too large"},400);let Y=A.entities.getUploadSaveHandler(X.type);if(!Y)return CQ({error:`No handler accepts uploads of type ${X.type}`},415);let H=await A.uploads.scoped({namespace:"upload",refKind:"upload",routePath:w}).save({filename:X.name,mediaType:X.type,content:Buffer.from(await X.arrayBuffer())}),W=await Y.handler({upload:{kind:"upload",id:H.id}},{interfaceType:"cms",userId:"operator"});if(!W.success)return CQ({error:W.error},502);return CQ({entityId:W.data.entityId,jobId:W.data.jobId},201)}function kB2(A,Q,w){if(w===void 0)return null;if(A.entities.getAdapter(Q)?.hasBody===!1)return CQ({error:`Entity type ${Q} does not have a body`},400);return null}function d0A(A,Q){if(qa(A))return{frontmatter:{},body:Q};try{let w=BQ(Q,f.record(f.string(),f.unknown()));return{frontmatter:w.metadata,body:w.content}}catch{return{frontmatter:{},body:Q}}}function CQ(A,Q=200){return new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}})}var _B2={name:"@brains/cms",version:"0.2.0-alpha.
|
|
8169
|
+
`),{object:X}=await A.ai.generateObject(B,IB2);return CQ({suggestion:X.suggestion})}async function txw(A){let Q=await A.messaging.send({type:"a2a:call:agents",payload:{}});if(!("success"in Q)||!Q.success)return CQ({agents:[]});let w=uxw.safeParse(Q.data);return CQ(w.success?w.data:{agents:[]})}async function exw(A,Q){let w;try{w=Sxw.parse(await Q.json())}catch{return CQ({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 CQ({error:Y?"Agent asking is unavailable":X},Y?503:400)}if($.data===void 0)return CQ({error:"Agent asking is unavailable"},503);let B=mxw.safeParse($.data);if(!B.success)return CQ({error:"Invalid response from agent"},502);return CQ({agentId:w.agent,response:B.data.response})}async function ARw(A,Q,w){let $=Number(Q.headers.get("content-length"));if(Number.isFinite($)&&$>bB2)return CQ({error:"Upload too large"},400);let B;try{B=await Q.formData()}catch{return CQ({error:"Invalid multipart upload"},400)}let X=B.get(cxw);if(!(X instanceof File))return CQ({error:"Missing upload file"},400);if(X.size>bB2)return CQ({error:"Upload too large"},400);let Y=A.entities.getUploadSaveHandler(X.type);if(!Y)return CQ({error:`No handler accepts uploads of type ${X.type}`},415);let H=await A.uploads.scoped({namespace:"upload",refKind:"upload",routePath:w}).save({filename:X.name,mediaType:X.type,content:Buffer.from(await X.arrayBuffer())}),W=await Y.handler({upload:{kind:"upload",id:H.id}},{interfaceType:"cms",userId:"operator"});if(!W.success)return CQ({error:W.error},502);return CQ({entityId:W.data.entityId,jobId:W.data.jobId},201)}function kB2(A,Q,w){if(w===void 0)return null;if(A.entities.getAdapter(Q)?.hasBody===!1)return CQ({error:`Entity type ${Q} does not have a body`},400);return null}function d0A(A,Q){if(qa(A))return{frontmatter:{},body:Q};try{let w=BQ(Q,f.record(f.string(),f.unknown()));return{frontmatter:w.metadata,body:w.content}}catch{return{frontmatter:{},body:Q}}}function CQ(A,Q=200){return new Response(JSON.stringify(A),{status:Q,headers:{"Content-Type":"application/json; charset=utf-8","Cache-Control":"no-store"}})}var _B2={name:"@brains/cms",version:"0.2.0-alpha.169",description:"CMS plugin for config and browser authoring routes",dependencies:{"@brains/auth-service":"workspace:*","@brains/console-theme":"workspace:*","@brains/plugins":"workspace:*","@brains/utils":"workspace:*","@codemirror/lang-markdown":"^6.5.0","@codemirror/language":"^6.12.4","@codemirror/state":"^6.7.1","@codemirror/view":"^6.43.6","@lezer/highlight":"^1.2.3",react:"^19.2.7","react-dom":"^19.2.7",streamdown:"^2.5.0"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/test-utils":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17","@types/react-dom":"^19.0.3","bun-types":"^1.3.14",eslint:"^10.5.0",typescript:"^7.0.2"},exports:{".":"./src/index.ts"},private:!0,scripts:{build:"bun scripts/build-ui.ts","build:ui":"bun scripts/build-ui.ts",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p ui-react/tsconfig.json"},type:"module"};var wRw=f.looseObject({label:f.string().optional(),pluralName:f.string().optional()}),$Rw=f.object({entityDisplay:f.record(f.string(),wRw).optional(),routePath:f.string().default("/cms")});class n0A extends Uw{constructor(A={}){super("cms",_B2,A,$Rw)}async onRegister(A){await super.onRegister(A),A.endpoints.register({label:"CMS",url:this.config.routePath,priority:40,visibility:"anchor"}),A.interactions.register({id:"cms",label:"CMS",description:"Edit and manage content through the browser CMS.",href:this.config.routePath,kind:"admin",priority:40,visibility:"anchor"})}getWebRoutes(){return LB2({routePath:this.config.routePath,getContext:()=>this.getContext(),resolveOperatorSession:BRw,getEntityDisplay:()=>this.config.entityDisplay??this.getContext().entityDisplay})}}function NM(A={}){return new n0A(A)}async function BRw(A){return Boolean(await A4()?.getOperatorSession(A))}fA();C0();fA();C0();var cH0=["StatsWidget","ListWidget","CustomWidget","PipelineWidget","IdentityWidget","ProfileWidget","SystemWidget"],XRw=new Set(cH0),YRw=f.enum(["public","trusted","anchor"]);function r0A(A){return XRw.has(A)}var NB2=f.object({label:f.string(),value:f.string(),tone:f.enum(["plain","good","warn"]).optional()}),jB2=f.object({id:f.string(),pluginId:f.string(),title:f.string(),description:f.string().optional(),group:f.string().min(1),priority:f.number().default(50),section:f.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:f.string(),visibility:YRw.default("public"),needsOperator:f.number().int().nonnegative().optional(),digest:f.array(NB2).max(4).optional()});class lH0{widgets=new Map;logger;constructor(A){this.logger=A.child("DashboardWidgetRegistry")}register(A){let w={...jB2.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(($)=>P9.hasPermission(w,$.visibility)).sort(($,B)=>$.priority-B.priority)}get size(){return this.widgets.size}}class pH0{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:H,clientScript:W,visibility:K="public",...U}=B;return{key:`${B.pluginId}:${B.id}`,widget:{...U,visibility:K,...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:dA(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:dA(w)}),{}}}async fetch(A,Q,w){return await this.getDashboardData()}}import{render as mRw}from"preact-render-to-string";var PB2=`* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
8170
8170
|
html, body { min-height: 100%; max-width: 100%; }
|
|
8171
8171
|
body {
|
|
8172
8172
|
font-family: var(--console-ui);
|
|
@@ -10048,7 +10048,7 @@ ${MB2}`;import{jsxDEV as jM,Fragment as xB2}from"preact/jsx-dev-runtime";functio
|
|
|
10048
10048
|
activate(resolveId(window.location.hash), false);
|
|
10049
10049
|
});
|
|
10050
10050
|
})();`;function nRw({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 rRw({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 oRw({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 e0A(A){return A.indexStatus?.ready??A.indexReady??A.appInfo.embeddings>0}function sRw({input:A}){let Q=e0A(A),w=A.activityLog?.[0],$=A.appInfo.entityCounts.length,B=A.appInfo.interactions.map((U)=>U.id).slice(0,3).join(" / "),X=A.indexStatus?.embeddedEntities??A.appInfo.embeddings,Y=A.indexStatus?.embeddableEntities,Z=A.indexStatus?(A.indexStatus.activeEmbeddingJobs??0)+(A.indexStatus.missingEmbeddings??0)+(A.indexStatus.staleEmbeddings??0):0,H=Y===void 0?`${X}`:`${X}/${Y}`,W=Z>0?`${H} embedded \xB7 ${Z} queued`:`${H} embedded`,K=(A.jobProgress??[]).some((U)=>U.status==="processing"||U.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:W},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("article",{class:`vital-card${K?" 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?AAA(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 aRw({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 tRw({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 eRw(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 AAA(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 SB2={created:{glyph:"\uFF0B",tone:""},updated:{glyph:"\u2713",tone:" ledger-glyph--ok"},deleted:{glyph:"\u2212",tone:" ledger-glyph--warn"}};function Avw({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:AAA(Q.timestamp)},void 0,!1,void 0,this),LA("span",{class:`ledger-glyph${SB2[Q.action].tone}`,"aria-hidden":"true",children:SB2[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 Qvw(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 wvw(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 $vw({status:A}){let Q=Qvw(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:wvw(A)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Bvw({input:A}){let Q=e0A(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($vw,{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 Xvw({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 ${eRw(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 Yvw={pending:"run",processing:"run",completed:"done",failed:"fail"},Zvw={pending:"pending",processing:"running",completed:"done",failed:"failed"};function fvw({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:AAA(Q.updatedAt)},void 0,!1,void 0,this),LA("td",{children:LA("span",{class:`status-pill status-pill--${Yvw[Q.status]}`,children:[Zvw[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 Hvw({input:A,tabs:Q,showOperatorGate:w}){let $=lRw(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(sRw,{input:A},void 0,!1,void 0,this),LA(aRw,{input:A},void 0,!1,void 0,this),w&&A.operatorAccess&&LA(nRw,{hiddenWidgetCount:A.operatorAccess.hiddenWidgetCount,loginUrl:A.operatorAccess.loginUrl},void 0,!1,void 0,this),LA("div",{class:"overview-grid",children:[LA(tRw,{cards:$},void 0,!1,void 0,this),LA(Avw,{events:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Wvw({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(vB2,{total:Q.appInfo.entities,entityCounts:Q.appInfo.entityCounts},void 0,!1,void 0,this),B&&LA(mB2,{children:[LA(Bvw,{input:Q},void 0,!1,void 0,this),Q.directorySyncStatus&&LA(Xvw,{status:Q.directorySyncStatus},void 0,!1,void 0,this),LA(fvw,{jobs:Q.jobProgress??[]},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$.map((Z)=>LA(s0A,{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(mB2,{children:[LA(hB2,{endpoints:Q.appInfo.endpoints,baseUrl:Q.baseUrl},void 0,!1,void 0,this),LA(EB2,{appInfo:Q.appInfo,now:w},void 0,!1,void 0,this),LA(CB2,{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(s0A,{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 Kvw({input:A}){let Q=iRw(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:Ur,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:OB2}},void 0,!1,void 0,this)]},void 0,!0,void 0,this),LA("body",{children:[LA(rRw,{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(RB2,{title:A.title,tagline:A.profile.description},void 0,!1,void 0,this),LA(oRw,{tabs:Q},void 0,!1,void 0,this),LA("div",{class:"canvas",children:LA("div",{class:"dashboard-tab-panels",children:[LA(Hvw,{input:A,tabs:Q,showOperatorGate:Boolean(w)},void 0,!1,void 0,this),Q.map((X)=>LA(Wvw,{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(TB2,{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:WP}},void 0,!1,void 0,this),LA("script",{dangerouslySetInnerHTML:{__html:KP}},void 0,!1,void 0,this),LA("script",{dangerouslySetInnerHTML:{__html:dRw}},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 cB2(A){return`<!doctype html>
|
|
10051
|
-
${mRw(LA(Kvw,{input:A},void 0,!1,void 0,this))}`}function Uvw(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function lB2(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 $=dH0([...new Set(A.groups)]).map((B)=>({group:B,label:aE(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}#${Uvw(B)}`,tag:"dashboard"}));if($.length>0)w.push({id:"tabs",label:"Dashboard",items:$});return w}function pB2(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 iB2={name:"@brains/dashboard",version:"0.2.0-alpha.168",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 Dvw=f.object({version:f.string().default("1.0.0"),routePath:f.string().default("/dashboard"),themeCSS:f.string().optional()}),qvw=f.object({id:f.string(),pluginId:f.string(),title:f.string(),description:f.string().optional(),group:f.string().min(1),priority:f.number().default(50),section:f.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:f.string(),visibility:f.enum(["public","trusted","anchor"]).default("public"),needsOperator:f.number().int().nonnegative().optional(),digest:f.array(f.object({label:f.string(),value:f.string(),tone:f.enum(["plain","good","warn"]).optional()})).max(4).optional(),component:f.custom().optional(),clientScript:f.string().optional(),dataProvider:f.custom((A)=>typeof A==="function",{message:"Expected dashboard widget data provider function"}),digestProvider:f.custom((A)=>typeof A==="function",{message:"Expected dashboard widget digest provider function"}).optional()}).superRefine((A,Q)=>{if(!r0A(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),zvw=f.object({pluginId:f.string(),widgetId:f.string().optional()}),Vvw=f.object({entityType:f.string(),entityId:f.string(),conversationId:f.string().optional()}),Jvw=f.object({id:f.string(),type:f.enum(["job","batch"]),status:f.enum(["pending","processing","completed","failed"]),message:f.string().optional(),progress:f.object({current:f.number(),total:f.number(),percentage:f.number()}).optional(),jobDetails:f.object({jobType:f.string(),priority:f.number(),retryCount:f.number()}).optional()}),Fvw=f.object({success:f.literal(!0),data:f.object({syncPath:f.string(),isInitialized:f.boolean(),watchEnabled:f.boolean(),lastSync:f.string().datetime().optional(),totalFiles:f.number().int().nonnegative().optional(),byEntityType:f.record(f.string(),f.number().int().nonnegative()).optional()})});function Ivw(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 QAA extends Uw{widgetRegistry=null;datasource=null;siteUrl;ctx;activityLog=[];jobProgress=[];constructor(A={}){super("dashboard",iB2,A,Dvw)}recordActivity(A,Q){let w=Vvw.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=Jvw.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:dA(Q)})}return}async getDirectorySyncStatus(){if(!this.ctx)return;try{let A=await this.ctx.messaging.send({type:"sync:status:request",payload:{}}),Q=Fvw.safeParse(A);return Q.success?Q.data.data:void 0}catch(A){this.logger.debug("Directory sync status unavailable",{error:dA(A)});return}}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new lH0(this.logger),this.datasource=new pH0(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=qvw.parse(Q.payload),$=Ivw(w);return this.widgetRegistry?.register($),this.logger.debug("Widget registered via messaging",{widgetId:w.id,pluginId:w.pluginId,rendererName:w.rendererName,builtIn:cH0.includes(w.rendererName)}),{success:!0}}catch(w){return this.logger.error("Failed to register widget",{error:dA(w),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let w=zvw.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:dA(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 A4()?.getOperatorSession(A),$=Boolean(w),B=$?"anchor":"public",X=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],Y=X.filter((x)=>P9.hasPermission(B,x.visibility)),Z=X.length-Y.length,[H,W,K,U]=await Promise.all([this.datasource.getDashboardData({permissionLevel:B,widgets:Y}),Q.appInfo(),this.getDirectorySyncStatus(),this.getIndexStatus()]),G=Q.identity.get(),q=Q.identity.getProfile(),V=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),J={...W,endpoints:W.endpoints.filter((x)=>P9.hasPermission(B,x.visibility)),interactions:W.interactions.filter((x)=>P9.hasPermission(B,x.visibility))},F=q.name||W.model||"Brain Dashboard",k=new URL(A.url),j=`${k.pathname}${k.search}`,_=encodeURIComponent(j),O=pB2(H.widgets,this.widgetRegistry),R={title:F,baseUrl:V,widgets:O.widgets,widgetScripts:O.widgetScripts,dashboardPath:this.config.routePath,surfaces:lb(Q.webRoutes.getRoutes(),{activeId:"dashboard",self:{id:"dashboard",href:this.config.routePath}}),character:G,profile:q,appInfo:J,activityLog:this.activityLog,jobProgress:this.jobProgress,...U!==void 0&&{indexStatus:U},...K!==void 0&&{directorySyncStatus:K},...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:$,hiddenWidgetCount:Z,loginUrl:`/login?return_to=${_}`,logoutUrl:`/logout?return_to=${_}`}};return new Response(cB2(R),{headers:{"Content-Type":"text/html; charset=utf-8"}})}},{path:"/api/console/jump",method:"GET",public:!0,handler:async(A)=>{if(!await A4()?.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((H)=>({entityType:H.entity.entityType,id:H.entity.id,title:H.entity.title??H.entity.id}))}catch{}let X=(this.widgetRegistry?.list({permissionLevel:"anchor"})??[]).map((Z)=>Z.group),Y=lb(w.webRoutes.getRoutes(),{activeId:"dashboard"}).find((Z)=>Z.id==="cms")?.href;return Response.json({groups:lB2({query:$,groups:[...X,"knowledge","system"],dashboardPath:this.config.routePath,cmsPath:Y,entities:B})})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function gL(A={}){return new QAA(A)}C0();var bvw=f.enum(["public","trusted","anchor"]),Lvw=f.object({label:f.string(),value:f.string(),tone:f.enum(["plain","good","warn"]).optional()}),kvw=f.object({id:f.string(),pluginId:f.string(),title:f.string(),description:f.string().optional(),group:f.string().min(1),priority:f.number(),section:f.enum(["primary","secondary","sidebar"]),rendererName:f.string(),visibility:bvw,needsOperator:f.number().int().nonnegative().optional(),digest:f.array(Lvw).max(4).optional(),component:f.custom().optional()}),_vw=f.object({widget:kvw,data:f.unknown()}),Nvw=f.object({widgets:f.record(f.string(),_vw)});fA();C0();fA();C0();import{h as lvw}from"preact";fA();Kf();k2();C0();var nH0=f.enum(["generating","draft","queued","published","failed"]),jvw=f.enum(["generating","draft","queued","published","failed"]),rH0=f.object({subject:f.string(),status:nH0,entityIds:f.array(f.string()).optional(),scheduledFor:f.string().datetime().optional(),sentAt:f.string().datetime().optional(),buttondownId:f.string().optional(),sourceEntityType:f.string().optional()}),dB2=f.object({subject:f.string(),status:nH0,entityIds:f.array(f.string()).optional(),scheduledFor:f.string().datetime().optional(),sentAt:f.string().datetime().optional(),buttondownId:f.string().optional(),sourceEntityType:f.string().optional(),error:f.string().optional()}),Pvw=f.object({subject:f.string(),status:jvw,entityIds:f.array(f.string()).optional(),scheduledFor:f.string().datetime().optional(),sentAt:f.string().datetime().optional(),buttondownId:f.string().optional(),sourceEntityType:f.string().optional(),error:f.string().optional()}),tE=TQ.extend({entityType:f.literal("newsletter"),metadata:Pvw});fA();class nB2 extends r2{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:tE,frontmatterSchema:rH0})}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 rB2=new nB2;fA();fA();k2();C0();var Mvw=f.looseObject({id:f.string().optional(),limit:f.number().optional(),page:f.number().optional(),pageSize:f.number().optional(),baseUrl:f.string().optional(),status:f.enum(["generating","draft","queued","published","failed"]).optional()}),Ovw=f.looseObject({entityType:f.string().optional(),query:Mvw.optional()});function oB2(A){try{let{content:Q}=BQ(A.content,rH0);return Q}catch{return A.content}}class wAA extends i5{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=Ovw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=oB2(A),w={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:lX(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:H}=await this.fetchList($,B,Y);return Q.parse(this.buildListResult(Z,H,$))}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 H=$.metadata.sourceEntityType??"post";X=(await Promise.all($.metadata.entityIds.map(async(K)=>{let U=await w.getEntity({entityType:H,id:K});if(U){let G=U.metadata;return{id:K,title:G.title??K,url:`/${H}s/${G.slug??K}`}}return null}))).filter((K)=>K!==null)}let Y=oB2($),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)}}fA();k2();C0();var xvw=f.object({prompt:f.string().optional().describe("AI generation prompt"),sourceEntityIds:f.array(f.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:f.enum(["post"]).optional().describe("Type of source entities"),content:f.string().optional().describe("Direct content (skip AI)"),subject:f.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:f.boolean().optional().describe("Create as queued (true) or draft (false)")});class $AA extends l4{constructor(A,Q){super(A,Q,{schema:xvw,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 G=X??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${B.length} source entities`});let V=(await Promise.all(B.map((_)=>this.context.entityService.getEntity({entityType:G,id:_})))).filter((_)=>_!=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:
|
|
10051
|
+
${mRw(LA(Kvw,{input:A},void 0,!1,void 0,this))}`}function Uvw(A){return A.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"group"}function lB2(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 $=dH0([...new Set(A.groups)]).map((B)=>({group:B,label:aE(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}#${Uvw(B)}`,tag:"dashboard"}));if($.length>0)w.push({id:"tabs",label:"Dashboard",items:$});return w}function pB2(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 iB2={name:"@brains/dashboard",version:"0.2.0-alpha.169",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 Dvw=f.object({version:f.string().default("1.0.0"),routePath:f.string().default("/dashboard"),themeCSS:f.string().optional()}),qvw=f.object({id:f.string(),pluginId:f.string(),title:f.string(),description:f.string().optional(),group:f.string().min(1),priority:f.number().default(50),section:f.enum(["primary","secondary","sidebar"]).default("primary"),rendererName:f.string(),visibility:f.enum(["public","trusted","anchor"]).default("public"),needsOperator:f.number().int().nonnegative().optional(),digest:f.array(f.object({label:f.string(),value:f.string(),tone:f.enum(["plain","good","warn"]).optional()})).max(4).optional(),component:f.custom().optional(),clientScript:f.string().optional(),dataProvider:f.custom((A)=>typeof A==="function",{message:"Expected dashboard widget data provider function"}),digestProvider:f.custom((A)=>typeof A==="function",{message:"Expected dashboard widget digest provider function"}).optional()}).superRefine((A,Q)=>{if(!r0A(A.rendererName)&&!A.component)Q.addIssue({code:"custom",message:"Custom dashboard widgets must register a Preact component.",path:["component"]})}),zvw=f.object({pluginId:f.string(),widgetId:f.string().optional()}),Vvw=f.object({entityType:f.string(),entityId:f.string(),conversationId:f.string().optional()}),Jvw=f.object({id:f.string(),type:f.enum(["job","batch"]),status:f.enum(["pending","processing","completed","failed"]),message:f.string().optional(),progress:f.object({current:f.number(),total:f.number(),percentage:f.number()}).optional(),jobDetails:f.object({jobType:f.string(),priority:f.number(),retryCount:f.number()}).optional()}),Fvw=f.object({success:f.literal(!0),data:f.object({syncPath:f.string(),isInitialized:f.boolean(),watchEnabled:f.boolean(),lastSync:f.string().datetime().optional(),totalFiles:f.number().int().nonnegative().optional(),byEntityType:f.record(f.string(),f.number().int().nonnegative()).optional()})});function Ivw(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 QAA extends Uw{widgetRegistry=null;datasource=null;siteUrl;ctx;activityLog=[];jobProgress=[];constructor(A={}){super("dashboard",iB2,A,Dvw)}recordActivity(A,Q){let w=Vvw.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=Jvw.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:dA(Q)})}return}async getDirectorySyncStatus(){if(!this.ctx)return;try{let A=await this.ctx.messaging.send({type:"sync:status:request",payload:{}}),Q=Fvw.safeParse(A);return Q.success?Q.data.data:void 0}catch(A){this.logger.debug("Directory sync status unavailable",{error:dA(A)});return}}async onRegister(A){this.siteUrl=A.siteUrl,this.ctx=A,this.widgetRegistry=new lH0(this.logger),this.datasource=new pH0(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=qvw.parse(Q.payload),$=Ivw(w);return this.widgetRegistry?.register($),this.logger.debug("Widget registered via messaging",{widgetId:w.id,pluginId:w.pluginId,rendererName:w.rendererName,builtIn:cH0.includes(w.rendererName)}),{success:!0}}catch(w){return this.logger.error("Failed to register widget",{error:dA(w),payload:Q.payload}),{success:!1,error:"Widget registration failed"}}}),A.messaging.subscribe("dashboard:unregister-widget",async(Q)=>{try{let w=zvw.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:dA(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 A4()?.getOperatorSession(A),$=Boolean(w),B=$?"anchor":"public",X=this.widgetRegistry?.list({permissionLevel:"anchor"})??[],Y=X.filter((x)=>P9.hasPermission(B,x.visibility)),Z=X.length-Y.length,[H,W,K,U]=await Promise.all([this.datasource.getDashboardData({permissionLevel:B,widgets:Y}),Q.appInfo(),this.getDirectorySyncStatus(),this.getIndexStatus()]),G=Q.identity.get(),q=Q.identity.getProfile(),V=this.siteUrl??(()=>{try{return new URL(A.url).origin}catch{return}})(),J={...W,endpoints:W.endpoints.filter((x)=>P9.hasPermission(B,x.visibility)),interactions:W.interactions.filter((x)=>P9.hasPermission(B,x.visibility))},F=q.name||W.model||"Brain Dashboard",k=new URL(A.url),j=`${k.pathname}${k.search}`,_=encodeURIComponent(j),O=pB2(H.widgets,this.widgetRegistry),R={title:F,baseUrl:V,widgets:O.widgets,widgetScripts:O.widgetScripts,dashboardPath:this.config.routePath,surfaces:lb(Q.webRoutes.getRoutes(),{activeId:"dashboard",self:{id:"dashboard",href:this.config.routePath}}),character:G,profile:q,appInfo:J,activityLog:this.activityLog,jobProgress:this.jobProgress,...U!==void 0&&{indexStatus:U},...K!==void 0&&{directorySyncStatus:K},...this.config.themeCSS!==void 0&&{themeCSS:this.config.themeCSS},operatorAccess:{isOperator:$,hiddenWidgetCount:Z,loginUrl:`/login?return_to=${_}`,logoutUrl:`/logout?return_to=${_}`}};return new Response(cB2(R),{headers:{"Content-Type":"text/html; charset=utf-8"}})}},{path:"/api/console/jump",method:"GET",public:!0,handler:async(A)=>{if(!await A4()?.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((H)=>({entityType:H.entity.entityType,id:H.entity.id,title:H.entity.title??H.entity.id}))}catch{}let X=(this.widgetRegistry?.list({permissionLevel:"anchor"})??[]).map((Z)=>Z.group),Y=lb(w.webRoutes.getRoutes(),{activeId:"dashboard"}).find((Z)=>Z.id==="cms")?.href;return Response.json({groups:lB2({query:$,groups:[...X,"knowledge","system"],dashboardPath:this.config.routePath,cmsPath:Y,entities:B})})}}]}async getTools(){return[]}getWidgetRegistry(){return this.widgetRegistry}}function gL(A={}){return new QAA(A)}C0();var bvw=f.enum(["public","trusted","anchor"]),Lvw=f.object({label:f.string(),value:f.string(),tone:f.enum(["plain","good","warn"]).optional()}),kvw=f.object({id:f.string(),pluginId:f.string(),title:f.string(),description:f.string().optional(),group:f.string().min(1),priority:f.number(),section:f.enum(["primary","secondary","sidebar"]),rendererName:f.string(),visibility:bvw,needsOperator:f.number().int().nonnegative().optional(),digest:f.array(Lvw).max(4).optional(),component:f.custom().optional()}),_vw=f.object({widget:kvw,data:f.unknown()}),Nvw=f.object({widgets:f.record(f.string(),_vw)});fA();C0();fA();C0();import{h as lvw}from"preact";fA();Kf();k2();C0();var nH0=f.enum(["generating","draft","queued","published","failed"]),jvw=f.enum(["generating","draft","queued","published","failed"]),rH0=f.object({subject:f.string(),status:nH0,entityIds:f.array(f.string()).optional(),scheduledFor:f.string().datetime().optional(),sentAt:f.string().datetime().optional(),buttondownId:f.string().optional(),sourceEntityType:f.string().optional()}),dB2=f.object({subject:f.string(),status:nH0,entityIds:f.array(f.string()).optional(),scheduledFor:f.string().datetime().optional(),sentAt:f.string().datetime().optional(),buttondownId:f.string().optional(),sourceEntityType:f.string().optional(),error:f.string().optional()}),Pvw=f.object({subject:f.string(),status:jvw,entityIds:f.array(f.string()).optional(),scheduledFor:f.string().datetime().optional(),sentAt:f.string().datetime().optional(),buttondownId:f.string().optional(),sourceEntityType:f.string().optional(),error:f.string().optional()}),tE=TQ.extend({entityType:f.literal("newsletter"),metadata:Pvw});fA();class nB2 extends r2{constructor(){super({entityType:"newsletter",purpose:"An email newsletter issue composed for subscribers.",schema:tE,frontmatterSchema:rH0})}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 rB2=new nB2;fA();fA();k2();C0();var Mvw=f.looseObject({id:f.string().optional(),limit:f.number().optional(),page:f.number().optional(),pageSize:f.number().optional(),baseUrl:f.string().optional(),status:f.enum(["generating","draft","queued","published","failed"]).optional()}),Ovw=f.looseObject({entityType:f.string().optional(),query:Mvw.optional()});function oB2(A){try{let{content:Q}=BQ(A.content,rH0);return Q}catch{return A.content}}class wAA extends i5{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=Ovw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}transformEntity(A){let Q=oB2(A),w={id:A.id,subject:A.metadata.subject,status:A.metadata.status,excerpt:lX(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:H}=await this.fetchList($,B,Y);return Q.parse(this.buildListResult(Z,H,$))}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 H=$.metadata.sourceEntityType??"post";X=(await Promise.all($.metadata.entityIds.map(async(K)=>{let U=await w.getEntity({entityType:H,id:K});if(U){let G=U.metadata;return{id:K,title:G.title??K,url:`/${H}s/${G.slug??K}`}}return null}))).filter((K)=>K!==null)}let Y=oB2($),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)}}fA();k2();C0();var xvw=f.object({prompt:f.string().optional().describe("AI generation prompt"),sourceEntityIds:f.array(f.string()).optional().describe("Entity IDs to include in newsletter (e.g., blog posts)"),sourceEntityType:f.enum(["post"]).optional().describe("Type of source entities"),content:f.string().optional().describe("Direct content (skip AI)"),subject:f.string().optional().describe("Newsletter subject (AI-generated if not provided)"),addToQueue:f.boolean().optional().describe("Create as queued (true) or draft (false)")});class $AA extends l4{constructor(A,Q){super(A,Q,{schema:xvw,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 G=X??"post";await this.reportProgress(Q,{progress:10,message:`Fetching ${B.length} source entities`});let V=(await Promise.all(B.map((_)=>this.context.entityService.getEntity({entityType:G,id:_})))).filter((_)=>_!=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:
|
|
10052
10052
|
|
|
10053
10053
|
${V.map((_)=>`## ${_.metadata.title}
|
|
10054
10054
|
|
|
@@ -10117,17 +10117,17 @@ Newsletter-specific guidelines:
|
|
|
10117
10117
|
- "Reply and let me know..."
|
|
10118
10118
|
- "Until next time..."
|
|
10119
10119
|
|
|
10120
|
-
The goal is to build a relationship with readers through valuable, authentic content.`});C0();fA();import{jsxDEV as NY,Fragment as gvw}from"preact/jsx-dev-runtime";var vvw=f.enum(["generating","draft","queued","published","failed"]),hvw=f.object({id:f.string(),subject:f.string(),status:vvw,excerpt:f.string(),created:f.string(),sentAt:f.string().optional(),url:f.string()}),Cvw=f.object({newsletters:f.array(hvw),totalCount:f.number(),pagination:T20.nullable()}),yvw=({newsletters:A,totalCount:Q,pageTitle:w,pagination:$,baseUrl:B="/newsletters"})=>{let X=w??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return NY(gvw,{children:[NY(Bw,{title:X,description:Y},void 0,!1,void 0,this),NY("div",{className:"newsletter-list bg-theme",children:NY("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[NY("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:X},void 0,!1,void 0,this),A.length===0?NY("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):NY("div",{className:"space-y-4",children:A.map((Z)=>NY(R6,{href:Z.url,children:[NY(x7,{className:"text-lg",children:Z.subject},void 0,!1,void 0,this),NY(Z4,{children:NY("div",{className:"flex items-center gap-3",children:[NY(LZ,{status:Z.status},void 0,!1,void 0,this),NY("span",{className:"text-sm text-theme-muted",children:rB(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&&NY("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&&NY(mV,{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)},aB2=s1({name:"newsletter-list",description:"Newsletter list page template",schema:Cvw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:yvw}});C0();fA();import{jsxDEV as F8,Fragment as uvw}from"preact/jsx-dev-runtime";var Evw=f.enum(["generating","draft","queued","published","failed"]),Tvw=f.object({id:f.string(),title:f.string(),url:f.string()}),tB2=f.object({id:f.string(),subject:f.string(),url:f.string()}),Svw=f.object({id:f.string(),subject:f.string(),status:Evw,content:f.string(),created:f.string(),updated:f.string(),sentAt:f.string().optional(),scheduledFor:f.string().optional(),sourceEntities:f.array(Tvw).optional(),prevNewsletter:tB2.nullable().optional(),nextNewsletter:tB2.nullable().optional()}),mvw=({subject:A,status:Q,content:w,created:$,sentAt:B,scheduledFor:X,sourceEntities:Y,prevNewsletter:Z,nextNewsletter:H})=>{let W=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],K=B??$,U=B?"Sent":"Created";return F8(uvw,{children:[F8(Bw,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),F8("section",{className:"newsletter-detail-section",children:F8("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:F8("div",{className:"max-w-3xl mx-auto",children:[F8(Iq,{items:W},void 0,!1,void 0,this),F8("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),F8("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[F8(LZ,{status:Q},void 0,!1,void 0,this),F8("span",{children:[U,": ",rB(K,{style:"long"})]},void 0,!0,void 0,this),X&&Q==="queued"&&F8("span",{children:["Scheduled for: ",rB(X,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&F8(R6,{variant:"compact",className:"mb-8",children:[F8("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),F8("ul",{className:"space-y-1",children:Y.map((G)=>F8("li",{children:F8("a",{href:G.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:G.title},void 0,!1,void 0,this)},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),F8(i9,{markdown:w},void 0,!1,void 0,this),(Z??H)&&F8("nav",{className:"mt-12 pt-8 border-t border-theme",children:F8("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[Z?F8(R6,{href:Z.url,variant:"compact",children:[F8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),F8("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):F8("div",{},void 0,!1,void 0,this),H&&F8(R6,{href:H.url,variant:"compact",className:"md:text-right",children:[F8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),F8("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:H.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},eB2=s1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:Svw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:mvw}});var oH0={name:"@brains/newsletter",version:"0.2.0-alpha.
|
|
10120
|
+
The goal is to build a relationship with readers through valuable, authentic content.`});C0();fA();import{jsxDEV as NY,Fragment as gvw}from"preact/jsx-dev-runtime";var vvw=f.enum(["generating","draft","queued","published","failed"]),hvw=f.object({id:f.string(),subject:f.string(),status:vvw,excerpt:f.string(),created:f.string(),sentAt:f.string().optional(),url:f.string()}),Cvw=f.object({newsletters:f.array(hvw),totalCount:f.number(),pagination:T20.nullable()}),yvw=({newsletters:A,totalCount:Q,pageTitle:w,pagination:$,baseUrl:B="/newsletters"})=>{let X=w??"Newsletters",Y=`Browse all ${Q} ${Q===1?"newsletter":"newsletters"}`;return NY(gvw,{children:[NY(Bw,{title:X,description:Y},void 0,!1,void 0,this),NY("div",{className:"newsletter-list bg-theme",children:NY("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-16 md:py-24",children:[NY("h1",{className:"text-3xl md:text-4xl font-bold text-heading mb-8",children:X},void 0,!1,void 0,this),A.length===0?NY("p",{className:"text-theme-muted italic",children:"No newsletters yet."},void 0,!1,void 0,this):NY("div",{className:"space-y-4",children:A.map((Z)=>NY(R6,{href:Z.url,children:[NY(x7,{className:"text-lg",children:Z.subject},void 0,!1,void 0,this),NY(Z4,{children:NY("div",{className:"flex items-center gap-3",children:[NY(LZ,{status:Z.status},void 0,!1,void 0,this),NY("span",{className:"text-sm text-theme-muted",children:rB(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&&NY("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&&NY(mV,{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)},aB2=s1({name:"newsletter-list",description:"Newsletter list page template",schema:Cvw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:yvw}});C0();fA();import{jsxDEV as F8,Fragment as uvw}from"preact/jsx-dev-runtime";var Evw=f.enum(["generating","draft","queued","published","failed"]),Tvw=f.object({id:f.string(),title:f.string(),url:f.string()}),tB2=f.object({id:f.string(),subject:f.string(),url:f.string()}),Svw=f.object({id:f.string(),subject:f.string(),status:Evw,content:f.string(),created:f.string(),updated:f.string(),sentAt:f.string().optional(),scheduledFor:f.string().optional(),sourceEntities:f.array(Tvw).optional(),prevNewsletter:tB2.nullable().optional(),nextNewsletter:tB2.nullable().optional()}),mvw=({subject:A,status:Q,content:w,created:$,sentAt:B,scheduledFor:X,sourceEntities:Y,prevNewsletter:Z,nextNewsletter:H})=>{let W=[{label:"Home",href:"/"},{label:"Newsletters",href:"/newsletters"},{label:A}],K=B??$,U=B?"Sent":"Created";return F8(uvw,{children:[F8(Bw,{title:A,description:`Newsletter: ${A}`},void 0,!1,void 0,this),F8("section",{className:"newsletter-detail-section",children:F8("div",{className:"container mx-auto px-6 md:px-8 py-12 md:py-20",children:F8("div",{className:"max-w-3xl mx-auto",children:[F8(Iq,{items:W},void 0,!1,void 0,this),F8("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),F8("div",{className:"flex flex-wrap items-center gap-3 mb-8 text-sm text-theme-muted",children:[F8(LZ,{status:Q},void 0,!1,void 0,this),F8("span",{children:[U,": ",rB(K,{style:"long"})]},void 0,!0,void 0,this),X&&Q==="queued"&&F8("span",{children:["Scheduled for: ",rB(X,{style:"long"})]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Y&&Y.length>0&&F8(R6,{variant:"compact",className:"mb-8",children:[F8("h3",{className:"text-sm font-medium text-heading mb-2",children:"Related Content"},void 0,!1,void 0,this),F8("ul",{className:"space-y-1",children:Y.map((G)=>F8("li",{children:F8("a",{href:G.url,className:"text-sm text-brand hover:text-brand-dark transition-colors",children:G.title},void 0,!1,void 0,this)},G.id,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),F8(i9,{markdown:w},void 0,!1,void 0,this),(Z??H)&&F8("nav",{className:"mt-12 pt-8 border-t border-theme",children:F8("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[Z?F8(R6,{href:Z.url,variant:"compact",children:[F8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Newer"},void 0,!1,void 0,this),F8("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):F8("div",{},void 0,!1,void 0,this),H&&F8(R6,{href:H.url,variant:"compact",className:"md:text-right",children:[F8("span",{className:"text-xs text-theme-muted uppercase tracking-wide",children:"Older"},void 0,!1,void 0,this),F8("span",{className:"block mt-1 font-medium text-heading group-hover:text-brand transition-colors truncate",children:H.subject},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},eB2=s1({name:"newsletter-detail",description:"Individual newsletter detail template",schema:Svw,dataSourceId:"newsletter:entities",requiredPermission:"public",layout:{component:mvw}});var oH0={name:"@brains/newsletter",version:"0.2.0-alpha.169",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 pvw=f.looseObject({}),ivw=f.object({prompt:f.string().optional(),content:f.string().optional()});class sH0 extends fw{entityType="newsletter";schema=tE;adapter=rB2;constructor(A={}){super("newsletter",oH0,A,pvw)}getEntityTypeConfig(){return{publish:{publishStatuses:["queued","published","failed"]}}}createGenerationHandler(A){return new $AA(this.logger,A)}getTemplates(){return{generation:sB2,"newsletter-list":aB2,"newsletter-detail":eB2}}getDataSources(){return[new wAA(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:()=>lvw(pr0,{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:dA(w)}}),{success:!0}}})}registerEvalHandlers(A){A.eval.registerHandler("generation",async(Q)=>{let w=ivw.parse(Q),$=w.content?`Create an engaging newsletter based on this content:
|
|
10121
10121
|
|
|
10122
10122
|
${w.content}`:w.prompt??"Write an engaging newsletter";return A.ai.generate({prompt:$,templateName:"newsletter:generation"})})}}function aH0(A={}){return new sH0(A)}fA();C0();C0();var nvw="https://api.buttondown.email/v1",rvw=f.enum(["unactivated","regular","unsubscribed","already_subscribed"]),ovw=f.enum(["draft","about_to_send","scheduled","sent"]),BAA=f.looseObject({id:f.string(),email:f.string(),subscriber_type:rvw,metadata:f.record(f.string(),f.string()).optional()}),A52=f.looseObject({id:f.string(),subject:f.string(),body:f.string().optional(),status:ovw,publish_date:f.string().optional()}),svw=f.looseObject({results:f.array(BAA),count:f.number()}),avw=f.looseObject({detail:f.string().optional(),message:f.string().optional(),code:f.string().optional()});class XAA extends Error{status;code;constructor(A,Q,w){super(A);this.name="ButtondownApiError",this.status=Q,this.code=w}}class PM{config;logger;constructor(A,Q){this.config=A,this.logger=Q}async request(A,Q={}){let w=`${nvw}${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=avw.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 XAA(`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 BAA.parse(await this.request("/subscribers",{method:"POST",body:JSON.stringify(Q)}))}catch(w){if(w instanceof XAA&&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 BAA.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 svw.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"}),A52.parse(await this.request("/emails",{method:"POST",body:JSON.stringify(Q)}))}async getEmail(A){return A52.parse(await this.request(`/emails/${A}`))}async validateCredentials(){try{return await this.request("/subscribers?page_size=1"),!0}catch{return!1}}}fA();C0();var Q52=f.string().email({pattern:f.regexes.html5Email}),tvw=f.object({email:Q52.describe("Email address to subscribe"),name:f.string().optional().describe("Subscriber name (optional)"),tags:f.array(f.string()).optional().describe("Tags to apply to subscriber (optional)")}),evw=f.object({email:Q52.describe("Email address to unsubscribe")}),Ahw=f.object({type:f.enum(["unactivated","regular","unsubscribed"]).optional().describe("Filter by subscriber status"),limit:f.number().optional().describe("Maximum number of results")});function w52(A,Q,w){let $=new PM(Q,w);return[i6(A,"subscribe","Subscribe an email address to the newsletter. Uses double opt-in by default.",tvw,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 p5({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 s7(dA(X))}}),i6(A,"unsubscribe","Unsubscribe an email address from the newsletter.",evw,async(B)=>{try{return await $.unsubscribe(B.email),p5({email:B.email},`Unsubscribed ${B.email} successfully`)}catch(X){return s7(dA(X))}}),i6(A,"list_subscribers","List newsletter subscribers with optional filtering by status.",Ahw,async(B)=>{try{let X=await $.listSubscribers({...B.type&&{type:B.type},...B.limit&&{limit:B.limit}});return p5({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 s7(dA(X))}})]}async function $52(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=dA(X);return $.error("Failed to send newsletter for post",{postId:B.id,error:Y}),{success:!1,error:Y}}}var Qhw=f.object({apiKey:f.string().optional().describe("Buttondown API key"),doubleOptIn:f.boolean().default(!0).describe("Require email confirmation for new subscribers"),autoSendOnPublish:f.boolean().default(!1).describe("Automatically send newsletter when a blog post is published")});class tH0 extends Uw{constructor(A={}){super("buttondown",oH0,A,Qhw)}async onRegister(A){if(A.messaging.subscribe("buttondown:is-configured",async()=>{return{success:!!this.config.apiKey}}),this.config.apiKey){let Q=new PM({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:dA($)}),{success:!1}}}),this.config.autoSendOnPublish)A.messaging.subscribe("publish:completed",async(w)=>{let $=await $52(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 w52(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 eH0(A={}){return new tH0(A)}var whw=f.object({apiKey:f.string().optional().describe("Buttondown API key"),doubleOptIn:f.boolean().optional().describe("Require email confirmation for new subscribers"),autoSendOnPublish:f.boolean().optional().describe("Automatically send newsletter when a blog post is published")});function B52(A={}){let Q=whw.safeParse(A);if(!Q.success)throw new iz("newsletter",Q.error.issues.map(($)=>({path:$.path.map(String).join("."),code:$.code,message:$.message})));let w=Q.data;return[aH0({}),eH0({...w.apiKey!==void 0&&{apiKey:w.apiKey},...w.doubleOptIn!==void 0&&{doubleOptIn:w.doubleOptIn},...w.autoSendOnPublish!==void 0&&{autoSendOnPublish:w.autoSendOnPublish}})]}fA();C0();import{existsSync as zhw,mkdirSync as Vhw,writeFileSync as Jhw}from"fs";import{join as YJ}from"path";C0();var YAA=f.object({baseFolder:f.string().default("_obsidian")});function ZAA(A){return typeof A==="object"&&A!==null}function za(A){if(!ZAA(A))return;let Q=A.def;return ZAA(Q)?Q:void 0}function X52(A){let Q=za(A)?.type;return typeof Q==="string"?Q:void 0}function $hw(A){return typeof A==="function"?A():A}function Bhw(A){let Q=A,w=!0,$=void 0,B=!1,X=!0;while(X){X=!1;let Z=za(Q),H=X52(Q);if(H==="optional"||H==="nullable"){w=!1,Q=Z?.innerType,X=!0;continue}if(H==="default")w=!1,B=!0,$=$hw(Z?.defaultValue),Q=Z?.innerType,X=!0}let Y={inner:Q,required:w};if(B)Y.defaultValue=$;return Y}function Xhw(A){let w=za(A)?.entries;if(!ZAA(w))return;let $=Object.values(w);if(!$.every((B)=>typeof B==="string"))return;return $}function Yhw(A){let Q=za(A),w=Q?.values;if(Array.isArray(w))return w[0];return Q?.value}function Y52(A){let Q=X52(A);if(Q==="enum"){let w=Xhw(A);return w?{type:"enum",enumValues:w}:{type:"enum"}}if(Q==="literal")return{type:"string",defaultValue:Yhw(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=za(A);return Y52(w?.out)}return{type:"unknown"}}function Z52(A){let Q=[];for(let[w,$]of Object.entries(A.shape)){let{inner:B,required:X,defaultValue:Y}=Bhw($),Z=Y52(B),H={name:w,type:Z.type,required:X},W=Y!==void 0?Y:Z.defaultValue;if(W!==void 0)H.defaultValue=W;if(Z.enumValues)H.enumValues=Z.enumValues;Q.push(H)}return Q}function Zhw(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 f52(A,Q,w=""){let $=["---"];for(let B of Q){let X=Zhw(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(`
|
|
10123
10123
|
`)}Pv();var fhw={string:"Input",number:"Number",boolean:"Boolean",date:"Date",enum:"Select",array:"Multi",unknown:"Input"};function Hhw(A){let Q={name:A.name,id:A.name,type:fhw[A.type]};if(A.type==="enum"&&A.enumValues){let w={};A.enumValues.forEach(($,B)=>{w[String(B)]=$}),Q.options=w}return Q}function H52(A,Q){let w={filesPaths:A,fields:Q.map(Hhw)};return`---
|
|
10124
10124
|
${jv(w)}---
|
|
10125
|
-
`}k2();Pv();var Whw=new Set(["entityType"]),Khw={base:"Notes"},Uhw=new Set(["note"]);function Ghw(A){let Q=["file.name"];for(let w of A)if(!Whw.has(w.name))Q.push(w.name);return Q}function Dhw(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function W52(A,Q){let w=Khw[A]??rfA(A),$=Dhw(Q),B=Ghw(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:[Uhw.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:X};return{filename:`${w}.base`,content:jv(Z),hasStatus:$}}function K52(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 jv(w)}function U52(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 jv(w)}var G52={name:"@brains/obsidian-vault",version:"0.2.0-alpha.
|
|
10125
|
+
`}k2();Pv();var Whw=new Set(["entityType"]),Khw={base:"Notes"},Uhw=new Set(["note"]);function Ghw(A){let Q=["file.name"];for(let w of A)if(!Whw.has(w.name))Q.push(w.name);return Q}function Dhw(A){return A.some((Q)=>Q.name==="status"&&Q.type==="enum")}function W52(A,Q){let w=Khw[A]??rfA(A),$=Dhw(Q),B=Ghw(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:[Uhw.has(A)?'file.folder == "/"':`file.inFolder("${A}")`]},views:X};return{filename:`${w}.base`,content:jv(Z),hasStatus:$}}function K52(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 jv(w)}function U52(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 jv(w)}var G52={name:"@brains/obsidian-vault",version:"0.2.0-alpha.169",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 Fhw={mkdir:Vhw,writeFile:Jhw,existsFile:zhw},Ihw=f.object({entityTypes:f.array(f.string()).optional().describe("Entity types to generate templates for (default: all)")});class fAA extends Uw{deps;constructor(A={},Q={}){super("obsidian-vault",G52,A,YAA);this.deps={...Fhw,...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[i6(this.id,"sync-templates","Generate Obsidian templates, Metadata Menu fileClass definitions, and Bases views for all registered entity types.",Ihw,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=YJ(A.dataDir,this.config.baseFolder),X=YJ(B,"templates"),Y=YJ(B,"fileClasses"),Z=YJ(B,"bases");this.deps.mkdir(X,{recursive:!0}),this.deps.mkdir(Y,{recursive:!0}),this.deps.mkdir(Z,{recursive:!0});let H=[],W=[],K=[],U=[],G=[],q=[];for(let F of $){let k=A.entities.getEffectiveFrontmatterSchema(F);if(!k){this.logger.debug(`Skipping ${F}: no frontmatter schema`),W.push(F);continue}let j=Z52(k),_=A.entities.getAdapter(F),O=_?.isSingleton===!0,R=H52(F,j);if(this.deps.writeFile(YJ(Y,`${F}.md`),R),K.push(F),O){G.push(F),this.logger.debug(`Generated fileClass (singleton): ${F}`);continue}let x=_?.getBodyTemplate()??"",M=f52(F,j,x);this.deps.writeFile(YJ(X,`${F}.md`),M),H.push(F);let S=W52(F,j),u=YJ(Z,S.filename);if(!this.deps.existsFile(u))this.deps.writeFile(u,S.content),U.push(F),this.logger.debug(`Generated base: ${S.filename}`);if(S.hasStatus)q.push({entityType:F,fields:j});this.logger.debug(`Generated template + fileClass: ${F}`)}let V=K52(G);if(V){let F=YJ(Z,"Settings.base");if(!this.deps.existsFile(F))this.deps.writeFile(F,V),U.push("Settings"),this.logger.debug("Generated Settings.base")}let J=U52(q);if(J){let F=YJ(Z,"Pipeline.base");if(!this.deps.existsFile(F))this.deps.writeFile(F,J),U.push("Pipeline"),this.logger.debug("Generated Pipeline.base")}return this.logger.info(`Synced ${H.length} templates, ${K.length} fileClasses, ${U.length} bases (${W.length} skipped)`),p5({generated:H,skipped:W,fileClasses:K,bases:U})}catch(w){return this.logger.error("Failed to sync",{error:w}),s7(w instanceof Error?w.message:"Unknown error")}}}function HAA(A={},Q){return new fAA(A,Q)}Q$();fA();fA();k2();H5();fA();C0();var AW0=f.enum(["draft","active","archived"]),QW0=f.enum(["anchor","trusted","public"]),wW0=f.enum(["agent-confirmed","manual"]),bhw=f.enum(["draft","active","archived"]),Lhw=f.enum(["anchor","trusted","public"]),khw=f.enum(["agent-confirmed","manual"]),nq=f.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,f.string().min(1).optional()),ZJ=f.preprocess((A)=>typeof A==="string"&&A.trim().length===0?void 0:A,f.string().min(1).optional()),WAA=f.object({event:f.string().min(1),target:f.string().min(1),operatorAction:f.boolean().optional(),label:ZJ,description:ZJ,operatorDescription:ZJ}),KAA=f.object({id:f.string().min(1),title:f.string().min(1),prompt:ZJ,requiredDetails:f.array(f.string().min(1)).default([]),instructions:f.array(f.string().min(1)).default([]),doneWhen:f.array(f.string().min(1)).default([]),transitions:f.array(WAA).default([])}),$W0=f.object({purpose:f.string().min(1),operatingRules:f.array(f.string().min(1)).default([]),initialState:f.string().min(1),states:f.array(KAA).min(1),finalStates:f.array(f.string().min(1)).min(1),nextPrompts:f.array(f.string().min(1)).default([])}),eE=f.object({title:f.string(),status:AW0.default("active"),audience:QW0.default("anchor"),trigger:nq.optional(),lifecycle:nq.optional(),once:f.boolean().optional(),starterText:nq.optional(),description:nq.optional(),starterPrompt:nq.optional(),completionMode:wW0.default("agent-confirmed")}),D52=f.object({title:f.string(),status:AW0,audience:QW0,trigger:nq.optional(),lifecycle:nq.optional(),once:f.boolean().optional(),starterText:nq.optional(),description:nq.optional(),starterPrompt:nq.optional(),completionMode:wW0}),_hw=f.object({title:f.string(),status:bhw,audience:Lhw,trigger:ZJ.optional(),lifecycle:ZJ.optional(),once:f.boolean().optional(),starterText:ZJ.optional(),description:ZJ.optional(),starterPrompt:ZJ.optional(),completionMode:khw}),AT=TQ.extend({entityType:f.literal("playbook"),metadata:_hw});class BW0 extends Y6{constructor(){super($W0,{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:UAA,parser:GAA},{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:Nhw,parser:jhw},{key:"label",label:"Label",type:"custom",formatter:UAA,parser:GAA},{key:"description",label:"Description",type:"string"},{key:"operatorDescription",label:"Operator Description",type:"custom",formatter:UAA,parser:GAA}]}]},{key:"finalStates",label:"Final States",type:"array",itemType:"string"},{key:"nextPrompts",label:"Next Prompts",type:"array",itemType:"string"}]})}}var Va=new BW0;function UAA(A){return typeof A==="string"?A:""}function GAA(A){let Q=A.trim();return Q.length>0?Q:void 0}function Nhw(A){return typeof A==="boolean"?String(A):""}function jhw(A){let Q=A.trim().toLowerCase();if(Q==="true")return!0;if(Q==="false")return!1;return}function DAA(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 Phw(A,w))Q.push(`Playbook state '${B}' is unreachable.`);return{valid:Q.length===0,errors:Q}}function QT(A){let Q=DAA(A);if(!Q.valid)throw Error(Q.errors.join(`
|
|
10126
10126
|
`))}function Phw(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 YW0 extends r2{constructor(){super({entityType:"playbook",purpose:"A guided multi-step workflow the assistant runs together with the user.",schema:AT,frontmatterSchema:eE})}createPlaybookContent(A,Q){return this.buildMarkdown(Va.format(Q),A)}parsePlaybookContent(A){let Q=this.parseFrontMatter(A,eE),w=this.extractBody(A).trim(),$=Mhw(w)?Ohw(w):Va.parse(w);return QT($),{frontmatter:eE.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 MM=new YW0;function Mhw(A){return/^##\s+Steps\s*$/im.test(A)}function Ohw(A){let Q=xhw(qAA(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:q1(Y.target),operatorAction:!0,label:Y.label})),...$.skip?[{event:"SKIP",target:q1($.skip.target),operatorAction:!0,label:$.skip.label}]:[]]}});return{purpose:Rhw(A,"Purpose"),operatingRules:q52(A,"Operating Rules"),initialState:Q[0]?.id??"",states:w,finalStates:[Q.at(-1)?.id??""],nextPrompts:q52(A,"Next Prompts")}}function xhw(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(`
|
|
10127
10127
|
`);return{title:$.title,id:q1($.title),...z52(B,"Say")?{prompt:z52(B,"Say")}:{},requiredDetails:XW0(B,"Required details"),instructions:XW0(B,"To do"),doneWhen:XW0(B,"Done when"),choices:vhw(B,"Choices"),...V52(B)?{skip:V52(B)}:{}}})}function qAA(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(`
|
|
10128
10128
|
`).trim()}function Rhw(A,Q){return qAA(A,Q).split(/\r?\n/).map((w)=>w.trim()).filter((w)=>w.length>0&&!w.startsWith("#")).join(`
|
|
10129
10129
|
`).trim()}function q52(A,Q){return J52(qAA(A,Q))}function z52(A,Q){return new RegExp(`^${Chw(Q)}:\\s*(.+?)\\s*$`,"im").exec(A)?.[1]?.trim()}function XW0(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 J52(B.join(`
|
|
10130
|
-
`))}function vhw(A,Q){return XW0(A,Q).map(hhw)}function hhw(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 V52(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 J52(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function Chw(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}C0();var ZW0=f.object({}).catchall(f.unknown()).transform(()=>({}));var fW0={name:"@brains/playbooks",version:"0.2.0-alpha.
|
|
10130
|
+
`))}function vhw(A,Q){return XW0(A,Q).map(hhw)}function hhw(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 V52(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 J52(A){return A.split(/\r?\n/).map((Q)=>/^-\s+(.+?)\s*$/.exec(Q)?.[1]?.trim()).filter((Q)=>Boolean(Q))}function Chw(A){return A.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}C0();var ZW0=f.object({}).catchall(f.unknown()).transform(()=>({}));var fW0={name:"@brains/playbooks",version:"0.2.0-alpha.169",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 ghw="playbook";class zAA extends fw{entityType=ghw;schema=AT;adapter=MM;constructor(A={}){super("playbook",fW0,A,ZW0)}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 VAA(A={}){return new zAA(A)}Q$();fA();C0();Kf();wl();function HW0(A,Q){return A.length===Q.length&&A.every((w,$)=>w===Q[$])}function JAA(A,Q){return Q==="NEXT"&&A.doneWhen.length>0}function WW0(A,Q){return Q.gateVerdicts.some((w)=>w.stateId===A.id&&HW0(w.goal,A.doneWhen)&&w.met)}function Ehw(A,Q,w){return w2.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,...JAA($,X.event)?{guard:()=>WW0($,w)}:{}}]))}}]}))})}function FAA(A,Q){let w=Ehw(Q.playbookId,A,Q);return w2.createActor(w,{snapshot:w.resolveState({value:Q.currentState})})}function Thw(A,Q,w){let $=FAA(Q,A);$.start();let B=$.getSnapshot().can({type:w});return $.stop(),B}function wT(A,Q,w){return w.transitions.filter(($)=>Thw(A,Q,$.event))}function Ja(A,Q,w){let $=new Set(wT(A,Q,w).map((B)=>`${B.event}\x00${B.target}`));return w.transitions.filter((B)=>!$.has(`${B.event}\x00${B.target}`))}function F52(A,Q){return A.evidence.filter((w)=>!w.stateId||w.stateId===Q)}function OM(A,Q){return A.states.find((w)=>w.id===Q)}function xM(A){let Q=A.operatorDescription??A.description??A.label;return Q?`- ${A.event} -> ${A.target}: ${Q}`:`- ${A.event} -> ${A.target}`}function I52(A,Q){if(Q.doneWhen.length===0)return"- no gated Done When conditions";let w=A.gateVerdicts.find(($)=>$.stateId===Q.id&&HW0($.goal,Q.doneWhen));if(!w)return`- Not yet met: ${Q.doneWhen.join("; ")}`;return w.met?`- Met: ${w.reason}`:`- Not yet met: ${w.reason}`}function b52(A,Q,w){let $=wT(A,Q,w),B=$.filter((H)=>H.operatorAction!==!0),X=$.filter((H)=>H.operatorAction===!0),Y=Ja(A,Q,w),Z=A.gateVerdicts.find((H)=>H.stateId===w.id&&HW0(H.goal,w.doneWhen));return[`Current state: ${w.id} (${w.title})`,"Instructions:",...w.instructions.map((H)=>`- ${H}`),"Done When:",...w.doneWhen.length>0?w.doneWhen.map((H)=>`- ${H}`):["- none"],"Goal status:",Z?`- ${Z.met?"Met":"Not yet met"}: ${Z.reason}`:"- Not checked yet.","Current-state information rules:","- If this state asks the operator for information, ask the operator for the missing current-run information.","- If the current operator message partially answers the state's prompt, do not repeat the original prompt; ask only for the next missing detail required by the state instructions.","- Do not answer the state's operator-facing prompt from memory, existing durable records, profile data, search, or retrieval tools.","- Setup facts must come from current-run evidence or current operator input, not ambient records.","Event selection rules:","- Blocked events are not valid events; do not call playbook_send_event with a blocked event.","- For gated durable states, operator-provided details are not enough to send NEXT; first complete the required system_create/system_update/system_delete action or use existing current-run evidence that the Done When condition has already been met.","- If the operator explicitly says they have not chosen, selected, asked for, or used one of the available actions, do not send any event.",'- Operator actions and choices are not generic continuation events; even if only one operator action is available, generic continuation like "yes", "next", or "continue" is not a valid selection.',"- If multiple events are available, ask the operator to pick one labeled action.","- A Skip-style operator action is never a default continuation; send it only when the operator positively selects or asks to skip.","Valid continuation events:",...B.length>0?B.map((H)=>xM(H)):["- none"],"Available operator actions:",...X.length>0?X.map((H)=>xM(H)):["- none"],"Blocked events:",...Y.length>0?Y.map((H)=>xM(H)):["- none"]].join(`
|
|
10131
10131
|
`)}function L52(A){let{run:Q,body:w,state:$,playbookTitle:B}=A,X=wT(Q,w,$),Y=X.filter((F)=>F.operatorAction!==!0),Z=X.filter((F)=>F.operatorAction===!0),H=Ja(Q,w,$),W=Y.map((F)=>xM(F)).join(`
|
|
10132
10132
|
`),K=Z.map((F)=>xM(F)).join(`
|
|
10133
10133
|
`),U=H.map((F)=>xM(F)).join(`
|
|
@@ -10201,9 +10201,9 @@ ${Object.entries(A).map(([w,$])=>`- ${w}: playbookId=${$.playbookId}, trigger=${
|
|
|
10201
10201
|
${A.guidance}`:B}}function C52(A){return{...A,evidence:A.evidence.map((Q)=>({...Q,data:ehw(Q.data)}))}}function ehw(A){return Object.fromEntries(["entityType","entityId","operation"].flatMap((Q)=>A[Q]!==void 0?[[Q,A[Q]]]:[]))}function ACw(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 QCw(A){if(!A)return"Continuing.";return A.prompt??`Continuing to ${A.title}.`}function y52(){return{promptTokens:0,completionTokens:0,totalTokens:0}}function g52(A,Q){let w=A.filter(Q),$=w.filter((B)=>B.status==="active"||B.status==="offered");return NAA($)??NAA(w)}function NAA(A){return[...A].sort((Q,w)=>(w.completedAt??w.updatedAt).localeCompare(Q.completedAt??Q.updatedAt))[0]}function wCw(A){return{async evaluate(Q){let w=Q.goal.join(`
|
|
10202
10202
|
`),$=await A.entityService.search({query:w,options:{limit:8,excludeTypes:["playbook"],visibilityScope:P8("anchor")}}),B=$Cw(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:rhw});return X}}}function $Cw(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,$)=>BCw($+1,w)):["No runtime evidence collected for this state."],"","## KB excerpts",...Q.length>0?Q.map((w,$)=>XCw($+1,w)):["No relevant KB excerpts found."]].join(`
|
|
10203
10203
|
`)}function BCw(A,Q){return`${A}. ${Q.kind} at ${Q.observedAt}: ${T52(Q.data)}`}function XCw(A,Q){return[`${A}. ${Q.entity.entityType}/${Q.entity.id} (score ${Q.score})`,`Excerpt: ${Q.excerpt}`,`Content: ${S52(Q.entity.content,1200)}`,`Metadata: ${T52(Q.entity.metadata)}`].join(`
|
|
10204
|
-
`)}function T52(A){try{return S52(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function S52(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var YCw={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function PAA(A={},Q={}){return new jAA(A,Q)}Q$();fA();C0();import{readFile as fCw}from"fs/promises";import{join as HCw}from"path";var m52={name:"@brains/rover-onboarding",version:"0.2.0-alpha.168",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 WCw=f.object({enabled:f.boolean().default(!1)}).strict(),u52=[{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 c52 extends Uw{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",m52,A,WCw)}async onReady(A){if(!this.config.enabled)return;for(let Q of u52)await this.seedPlaybookIfMissing(A,Q);for(let Q of u52){if(!Q.starter)continue;await A.messaging.send({type:kx,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let $=await fCw(HCw(import.meta.dir,"..","content","playbook",Q.fileName),"utf8");await A.entityService.createEntityFromMarkdown({input:{entityType:"playbook",id:Q.id,markdown:$}})}}function l52(A={}){return new c52(A)}fA();C0();C0();fA();var MAA=f.enum(["new","planned","in-progress","done","declined"]),OAA=f.enum(["low","medium","high","critical"]),KCw=f.enum(["new","planned","in-progress","done","declined"]),UCw=f.enum(["low","medium","high","critical"]),Fa=f.object({title:f.string(),status:MAA,priority:OAA.default("medium"),requested:f.number().int().default(1),declinedReason:f.string().optional()}),GCw=f.object({title:f.string(),status:MAA,priority:OAA,requested:f.number().int(),slug:f.string()}),DCw=f.object({title:f.string(),status:KCw,priority:UCw,requested:f.number().int(),slug:f.string()}),Ia=TQ.extend({entityType:f.literal("wish"),metadata:DCw});C0();var xAA=f.object({}).catchall(f.unknown()).transform(()=>({}));fA();k2();class ba extends r2{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:Ia,frontmatterSchema:Fa})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,Fa);return{frontmatter:Fa.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),w=q1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:w}}}}var p52=new ba;k2();k2();async function i52(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=q1(Q.title);return A.getEntity({entityType:"wish",id:X})}class DW0{logger;context;adapter=new ba;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 i52({search:(W)=>this.context.entityService.search(W),getEntity:(W)=>this.context.entityService.getEntity(W),similarityThreshold:0.85},{title:$,description:B});if(X){let{frontmatter:W,description:K}=this.adapter.parseWishContent(X.content),U=W.requested+1,G=this.adapter.createWishContent({...W,requested:U},K);return await this.context.entityService.updateEntity({entity:{...X,content:G,metadata:{...X.metadata,requested:U}}}),this.logger.info("Incremented wish request count",{id:X.id,requested:U}),{success:!0,entityId:X.id,existed:!0,requested:U}}let Y=q1($),Z=A.options?.priority??"medium",H=this.adapter.createWishContent({title:$,status:"new",priority:Z,requested:1},B);return await this.context.entityService.createEntity({entity:{id:Y,entityType:"wish",content:H,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 d52={critical:0,high:1,medium:2,low:3};function n52(A){A.sort((Q,w)=>{let $=w.metadata.requested-Q.metadata.requested;if($!==0)return $;return d52[Q.metadata.priority]-d52[w.metadata.priority]})}var r52={name:"@brains/wishlist",version:"0.2.0-alpha.168",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 zCw=f.object({items:f.array(f.object({name:f.string(),count:f.number()}))}),VCw="wish";class o52 extends fw{entityType=VCw;schema=Ia;adapter=p52;constructor(A={}){super("wishlist",r52,A,xAA)}async interceptCreate(A,Q,w){let $=await new DW0(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:$}=zCw.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 n52(w),{items:w.map(($)=>({id:$.id,name:$.metadata.title,count:$.metadata.requested,priority:$.metadata.priority,status:$.metadata.status}))}}}}),{success:!0}});let Q=new DW0(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 JCw(A={}){return new o52(A)}var qW0=JCw;fA();fA();C0();var La=f.object({title:f.string(),target:f.string()}),s52=f.object({title:f.string(),target:f.string(),slug:f.string().optional()}),ka=TQ.extend({entityType:f.literal("prompt"),metadata:s52});fA();k2();class RAA extends r2{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:ka,frontmatterSchema:La})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,La);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,La),w=q1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:w}}}}var vAA=new RAA;var a52={name:"@brains/prompt",version:"0.2.0-alpha.168",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 ICw="prompt";class hAA extends fw{entityType=ICw;schema=ka;adapter=vAA;constructor(){super("prompt",a52,{},o7)}getEntityTypeConfig(){return{embeddable:!1}}}function vM(){return new hAA}fA();C0();C0();class zW0{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=LCw.parse(await $.json());return{photos:B.results.map(kCw),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 bCw=f.looseObject({id:f.string(),description:f.string().nullable(),alt_description:f.string().nullable(),urls:f.looseObject({raw:f.url(),full:f.url(),regular:f.url(),small:f.url(),thumb:f.url()}),links:f.looseObject({html:f.url(),download_location:f.url()}),user:f.looseObject({name:f.string(),links:f.looseObject({html:f.url()})}),width:f.number().int().nonnegative(),height:f.number().int().nonnegative()}),LCw=f.looseObject({total:f.number().int().nonnegative(),total_pages:f.number().int().nonnegative(),results:f.array(bCw)});function kCw(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}}C0();async function VW0(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 _Cw={query:f.string().describe("Search terms for stock photos"),perPage:f.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:f.number().min(1).default(1).describe("Page number")},NCw={photoId:f.string().describe("Photo ID from search results"),downloadLocation:f.url().describe("Download tracking URL (required by provider ToS)"),photographerName:f.string().describe("Photographer name for attribution"),photographerUrl:f.url().describe("Photographer profile URL for attribution"),sourceUrl:f.url().describe("Photo page URL on provider"),imageUrl:f.url().describe("Image URL to download"),title:f.string().optional().describe("Image entity title"),alt:f.string().optional().describe("Alt text for the image"),targetEntityType:f.string().optional().describe("Entity type to set cover image on"),targetEntityId:f.string().optional().describe("Entity ID to set cover image on")},jCw=f.object({query:f.string(),perPage:f.number().min(1).max(30).default(10),page:f.number().min(1).default(1)}),PCw=f.object({photoId:f.string(),downloadLocation:f.url(),photographerName:f.string(),photographerUrl:f.url(),sourceUrl:f.url(),imageUrl:f.url(),title:f.string().optional(),alt:f.string().optional(),targetEntityType:f.string().optional(),targetEntityId:f.string().optional()});function t52(A,Q){return[MCw(A,Q),OCw(A,Q)]}function MCw(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:_Cw,visibility:"anchor",sideEffects:"none",handler:async(w)=>{let $=jCw.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 OCw(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:NCw,visibility:"anchor",sideEffects:"external",handler:async(w)=>{let $=PCw.safeParse(w);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:H,imageUrl:W,title:K,alt:U,targetEntityType:G,targetEntityId:q}=$.data,V={photographerName:Y,photographerUrl:Z,sourceUrl:H},J=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:W}}}});if(J[0]){let j={imageEntityId:J[0].id,alreadyExisted:!0,attribution:V};if(G&&q)j.coverSet=await VW0(Q.entityService,G,q,J[0].id);return{success:!0,data:j}}let F=await Q.jobs.enqueue({type:"select-photo",data:{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:H,imageUrl:W,...K!==void 0?{title:K}:{},...U!==void 0?{alt:U}:{},...G!==void 0?{targetEntityType:G}:{},...q!==void 0?{targetEntityId:q}:{}}}),k={imageEntityId:B,alreadyExisted:!1,attribution:V,jobId:F,status:"generating"};if(G&&q)k.coverSet=!1;return{success:!0,data:k}}}}fA();C0();r4();var xCw=f.object({photoId:f.string(),downloadLocation:f.url(),photographerName:f.string(),photographerUrl:f.url(),sourceUrl:f.url(),imageUrl:f.url(),title:f.string().optional(),alt:f.string().optional(),targetEntityType:f.string().optional(),targetEntityId:f.string().optional()});class CAA extends z6{deps;constructor(A,Q){super(A,{schema:xCw,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=bf.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 VW0(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}}}r4();var e52={name:"@brains/stock-photo",version:"0.2.0-alpha.168",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 vCw=f.object({provider:f.enum(["unsplash"]).default("unsplash"),apiKey:f.string().optional().describe("Stock photo provider API key")});class yAA extends Uw{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",e52,A,vCw);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=t52(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??kW,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new CAA(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??kW}))}createProvider(){return new zW0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function gAA(A={},Q={}){return new yAA(A,Q)}fA();C0();fA();fA();C0();var A92=f.enum(["ai","foundation","work"]),Q92=f.object({suffix:A92,title:f.string(),body:f.string(),linkLabel:f.string(),linkHref:f.string()}),_a=f.object({eyebrow:f.string(),headline:f.string(),cards:f.array(Q92).min(1)}),EAA=f.object({title:f.string(),slug:f.string(),status:f.enum(["draft","published"])}),hCw=f.object({title:f.string(),slug:f.string(),status:f.enum(["draft","published"])}),Na=TQ.extend({entityType:f.literal("ecosystem-section"),metadata:hCw});class w92 extends r2{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:Na,frontmatterSchema:EAA})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var TAA=new w92;C0();function CCw(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function SAA(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function ja(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function JW0(A){let Q=CCw(A),$=SAA(Q,"Cards").split(/^### Card \d+\s*$/m).map((B)=>B.trim()).filter(Boolean);return _a.parse({eyebrow:SAA(Q,"Eyebrow"),headline:SAA(Q,"Headline"),cards:$.map((B)=>({suffix:ja(B,"Suffix"),title:ja(B,"Title"),body:ja(B,"Body"),linkLabel:ja(B,"Link Label"),linkHref:ja(B,"Link Href")}))})}function $92(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(`
|
|
10204
|
+
`)}function T52(A){try{return S52(JSON.stringify(A),1200)}catch{return"[unserializable]"}}function S52(A,Q){return A.length>Q?`${A.slice(0,Q)}\u2026`:A}var YCw={async evaluate(){return{met:!1,reason:"No playbook goal check is configured."}}};function PAA(A={},Q={}){return new jAA(A,Q)}Q$();fA();C0();import{readFile as fCw}from"fs/promises";import{join as HCw}from"path";var m52={name:"@brains/rover-onboarding",version:"0.2.0-alpha.169",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 WCw=f.object({enabled:f.boolean().default(!1)}).strict(),u52=[{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 c52 extends Uw{dependencies=["playbook","playbooks"];constructor(A={}){super("rover-onboarding",m52,A,WCw)}async onReady(A){if(!this.config.enabled)return;for(let Q of u52)await this.seedPlaybookIfMissing(A,Q);for(let Q of u52){if(!Q.starter)continue;await A.messaging.send({type:kx,payload:Q.starter})}}async seedPlaybookIfMissing(A,Q){if(await A.entityService.getEntity({entityType:"playbook",id:Q.id,visibilityScope:"restricted"}))return;let $=await fCw(HCw(import.meta.dir,"..","content","playbook",Q.fileName),"utf8");await A.entityService.createEntityFromMarkdown({input:{entityType:"playbook",id:Q.id,markdown:$}})}}function l52(A={}){return new c52(A)}fA();C0();C0();fA();var MAA=f.enum(["new","planned","in-progress","done","declined"]),OAA=f.enum(["low","medium","high","critical"]),KCw=f.enum(["new","planned","in-progress","done","declined"]),UCw=f.enum(["low","medium","high","critical"]),Fa=f.object({title:f.string(),status:MAA,priority:OAA.default("medium"),requested:f.number().int().default(1),declinedReason:f.string().optional()}),GCw=f.object({title:f.string(),status:MAA,priority:OAA,requested:f.number().int(),slug:f.string()}),DCw=f.object({title:f.string(),status:KCw,priority:UCw,requested:f.number().int(),slug:f.string()}),Ia=TQ.extend({entityType:f.literal("wish"),metadata:DCw});C0();var xAA=f.object({}).catchall(f.unknown()).transform(()=>({}));fA();k2();class ba extends r2{constructor(){super({entityType:"wish",purpose:"An explicitly recorded capability or outcome the assistant cannot currently fulfill, kept for future planning.",schema:Ia,frontmatterSchema:Fa})}createWishContent(A,Q){return this.buildMarkdown(Q,A)}parseWishContent(A){let Q=this.parseFrontMatter(A,Fa);return{frontmatter:Fa.parse(Q),description:this.extractBody(A).trim()}}fromMarkdown(A){let{frontmatter:Q}=this.parseWishContent(A),w=q1(Q.title);return{content:A,entityType:"wish",metadata:{title:Q.title,status:Q.status,priority:Q.priority,requested:Q.requested,slug:w}}}}var p52=new ba;k2();k2();async function i52(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=q1(Q.title);return A.getEntity({entityType:"wish",id:X})}class DW0{logger;context;adapter=new ba;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 i52({search:(W)=>this.context.entityService.search(W),getEntity:(W)=>this.context.entityService.getEntity(W),similarityThreshold:0.85},{title:$,description:B});if(X){let{frontmatter:W,description:K}=this.adapter.parseWishContent(X.content),U=W.requested+1,G=this.adapter.createWishContent({...W,requested:U},K);return await this.context.entityService.updateEntity({entity:{...X,content:G,metadata:{...X.metadata,requested:U}}}),this.logger.info("Incremented wish request count",{id:X.id,requested:U}),{success:!0,entityId:X.id,existed:!0,requested:U}}let Y=q1($),Z=A.options?.priority??"medium",H=this.adapter.createWishContent({title:$,status:"new",priority:Z,requested:1},B);return await this.context.entityService.createEntity({entity:{id:Y,entityType:"wish",content:H,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 d52={critical:0,high:1,medium:2,low:3};function n52(A){A.sort((Q,w)=>{let $=w.metadata.requested-Q.metadata.requested;if($!==0)return $;return d52[Q.metadata.priority]-d52[w.metadata.priority]})}var r52={name:"@brains/wishlist",version:"0.2.0-alpha.169",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 zCw=f.object({items:f.array(f.object({name:f.string(),count:f.number()}))}),VCw="wish";class o52 extends fw{entityType=VCw;schema=Ia;adapter=p52;constructor(A={}){super("wishlist",r52,A,xAA)}async interceptCreate(A,Q,w){let $=await new DW0(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:$}=zCw.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 n52(w),{items:w.map(($)=>({id:$.id,name:$.metadata.title,count:$.metadata.requested,priority:$.metadata.priority,status:$.metadata.status}))}}}}),{success:!0}});let Q=new DW0(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 JCw(A={}){return new o52(A)}var qW0=JCw;fA();fA();C0();var La=f.object({title:f.string(),target:f.string()}),s52=f.object({title:f.string(),target:f.string(),slug:f.string().optional()}),ka=TQ.extend({entityType:f.literal("prompt"),metadata:s52});fA();k2();class RAA extends r2{constructor(){super({entityType:"prompt",purpose:"A reusable prompt or instruction template.",schema:ka,frontmatterSchema:La})}toMarkdown(A){let Q=this.extractBody(A.content),w=this.parseFrontMatter(A.content,La);return this.buildMarkdown(Q,w)}fromMarkdown(A){let Q=this.parseFrontMatter(A,La),w=q1(Q.target.replace(/:/g,"-"));return{content:A,entityType:"prompt",metadata:{title:Q.title,target:Q.target,slug:w}}}}var vAA=new RAA;var a52={name:"@brains/prompt",version:"0.2.0-alpha.169",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 ICw="prompt";class hAA extends fw{entityType=ICw;schema=ka;adapter=vAA;constructor(){super("prompt",a52,{},o7)}getEntityTypeConfig(){return{embeddable:!1}}}function vM(){return new hAA}fA();C0();C0();class zW0{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=LCw.parse(await $.json());return{photos:B.results.map(kCw),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 bCw=f.looseObject({id:f.string(),description:f.string().nullable(),alt_description:f.string().nullable(),urls:f.looseObject({raw:f.url(),full:f.url(),regular:f.url(),small:f.url(),thumb:f.url()}),links:f.looseObject({html:f.url(),download_location:f.url()}),user:f.looseObject({name:f.string(),links:f.looseObject({html:f.url()})}),width:f.number().int().nonnegative(),height:f.number().int().nonnegative()}),LCw=f.looseObject({total:f.number().int().nonnegative(),total_pages:f.number().int().nonnegative(),results:f.array(bCw)});function kCw(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}}C0();async function VW0(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 _Cw={query:f.string().describe("Search terms for stock photos"),perPage:f.number().min(1).max(30).default(10).describe("Results per page (1-30)"),page:f.number().min(1).default(1).describe("Page number")},NCw={photoId:f.string().describe("Photo ID from search results"),downloadLocation:f.url().describe("Download tracking URL (required by provider ToS)"),photographerName:f.string().describe("Photographer name for attribution"),photographerUrl:f.url().describe("Photographer profile URL for attribution"),sourceUrl:f.url().describe("Photo page URL on provider"),imageUrl:f.url().describe("Image URL to download"),title:f.string().optional().describe("Image entity title"),alt:f.string().optional().describe("Alt text for the image"),targetEntityType:f.string().optional().describe("Entity type to set cover image on"),targetEntityId:f.string().optional().describe("Entity ID to set cover image on")},jCw=f.object({query:f.string(),perPage:f.number().min(1).max(30).default(10),page:f.number().min(1).default(1)}),PCw=f.object({photoId:f.string(),downloadLocation:f.url(),photographerName:f.string(),photographerUrl:f.url(),sourceUrl:f.url(),imageUrl:f.url(),title:f.string().optional(),alt:f.string().optional(),targetEntityType:f.string().optional(),targetEntityId:f.string().optional()});function t52(A,Q){return[MCw(A,Q),OCw(A,Q)]}function MCw(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:_Cw,visibility:"anchor",sideEffects:"none",handler:async(w)=>{let $=jCw.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 OCw(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:NCw,visibility:"anchor",sideEffects:"external",handler:async(w)=>{let $=PCw.safeParse(w);if(!$.success)return{success:!1,error:`Invalid input: ${$.error.message}`};let{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:H,imageUrl:W,title:K,alt:U,targetEntityType:G,targetEntityId:q}=$.data,V={photographerName:Y,photographerUrl:Z,sourceUrl:H},J=await Q.entityService.listEntities({entityType:"image",options:{limit:1,filter:{metadata:{sourceUrl:W}}}});if(J[0]){let j={imageEntityId:J[0].id,alreadyExisted:!0,attribution:V};if(G&&q)j.coverSet=await VW0(Q.entityService,G,q,J[0].id);return{success:!0,data:j}}let F=await Q.jobs.enqueue({type:"select-photo",data:{photoId:B,downloadLocation:X,photographerName:Y,photographerUrl:Z,sourceUrl:H,imageUrl:W,...K!==void 0?{title:K}:{},...U!==void 0?{alt:U}:{},...G!==void 0?{targetEntityType:G}:{},...q!==void 0?{targetEntityId:q}:{}}}),k={imageEntityId:B,alreadyExisted:!1,attribution:V,jobId:F,status:"generating"};if(G&&q)k.coverSet=!1;return{success:!0,data:k}}}}fA();C0();r4();var xCw=f.object({photoId:f.string(),downloadLocation:f.url(),photographerName:f.string(),photographerUrl:f.url(),sourceUrl:f.url(),imageUrl:f.url(),title:f.string().optional(),alt:f.string().optional(),targetEntityType:f.string().optional(),targetEntityId:f.string().optional()});class CAA extends z6{deps;constructor(A,Q){super(A,{schema:xCw,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=bf.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 VW0(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}}}r4();var e52={name:"@brains/stock-photo",version:"0.2.0-alpha.169",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 vCw=f.object({provider:f.enum(["unsplash"]).default("unsplash"),apiKey:f.string().optional().describe("Stock photo provider API key")});class yAA extends Uw{deps;cachedTools=null;constructor(A={},Q={}){super("stock-photo",e52,A,vCw);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=t52(this.id,{provider:Q,entityService:A.entityService,fetchImage:this.deps.fetchImage??kW,jobs:A.jobs}),this.cachedTools}async registerJobHandlers(){if(!this.config.apiKey)return;let A=this.getContext();A.jobs.registerHandler("select-photo",new CAA(this.logger.child("SelectPhotoJobHandler"),{provider:this.createProvider(),entityService:A.entityService,fetchImage:this.deps.fetchImage??kW}))}createProvider(){return new zW0(this.config.apiKey??"",this.deps.fetch??globalThis.fetch)}}function gAA(A={},Q={}){return new yAA(A,Q)}fA();C0();fA();fA();C0();var A92=f.enum(["ai","foundation","work"]),Q92=f.object({suffix:A92,title:f.string(),body:f.string(),linkLabel:f.string(),linkHref:f.string()}),_a=f.object({eyebrow:f.string(),headline:f.string(),cards:f.array(Q92).min(1)}),EAA=f.object({title:f.string(),slug:f.string(),status:f.enum(["draft","published"])}),hCw=f.object({title:f.string(),slug:f.string(),status:f.enum(["draft","published"])}),Na=TQ.extend({entityType:f.literal("ecosystem-section"),metadata:hCw});class w92 extends r2{constructor(){super({entityType:"ecosystem-section",purpose:"A section of the Rizom ecosystem overview.",schema:Na,frontmatterSchema:EAA})}fromMarkdown(A){return{content:A,entityType:"ecosystem-section",metadata:this.parseFrontmatter(A)}}}var TAA=new w92;C0();function CCw(A){return A.replace(/^---\n[\s\S]*?\n---\n?/,"")}function SAA(A,Q){return new RegExp(`(?:^|\\n)## ${Q}\\s*\\n([\\s\\S]*?)(?=\\n## |$)`).exec(A)?.[1]?.trim()??""}function ja(A,Q){return new RegExp(`(?:^|\\n)#### ${Q}\\s*\\n([\\s\\S]*?)(?=\\n#### |\\n### |$)`).exec(A)?.[1]?.trim()??""}function JW0(A){let Q=CCw(A),$=SAA(Q,"Cards").split(/^### Card \d+\s*$/m).map((B)=>B.trim()).filter(Boolean);return _a.parse({eyebrow:SAA(Q,"Eyebrow"),headline:SAA(Q,"Headline"),cards:$.map((B)=>({suffix:ja(B,"Suffix"),title:ja(B,"Title"),body:ja(B,"Body"),linkLabel:ja(B,"Link Label"),linkHref:ja(B,"Link Href")}))})}function $92(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(`
|
|
10205
10205
|
`)}var yCw=f.looseObject({query:f.object({id:f.string().optional()}).optional()});class FW0{id="rizom-ecosystem:entities";name="Rizom Ecosystem";description="Fetches an ecosystem-section entity for rendering";async fetch(A,Q,w){let B=yCw.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(JW0(X.content))}}import{jsxDEV as TCw}from"preact/jsx-dev-runtime";var gCw="px-6 md:px-10 xl:px-20",ECw=`${gCw} relative z-[1]`,B92=({id:A,className:Q,children:w})=>TCw("section",{id:A,className:g2(ECw,Q),children:w},void 0,!1,void 0,this);import{jsxDEV as IW0}from"preact/jsx-dev-runtime";var SCw=new Map([["work","text-accent"],["foundation","text-secondary"],["ai","text-accent-bright"]]),X92=({name:A="rizom",brandSuffix:Q,className:w,dotClassName:$,suffixClassName:B})=>{let X=SCw.get(Q);return IW0("span",{className:g2("inline-flex items-baseline gap-0 font-display font-medium tracking-[-0.015em] [font-variation-settings:'opsz'_24]",w),children:[IW0("span",{className:"text-theme",children:A},void 0,!1,void 0,this),IW0("span",{className:g2(X??"text-accent",$),children:"."},void 0,!1,void 0,this),IW0("span",{className:g2("italic font-normal text-theme-muted",B),children:Q},void 0,!1,void 0,this)]},void 0,!0,void 0,this)};import{Fragment as mAA}from"preact";import{jsxDEV as Pa}from"preact/jsx-dev-runtime";var mCw=/(\*[^*]+\*)/;function Y92(A,Q){let w=A.split(`
|
|
10206
|
-
`);return Pa(mAA,{children:w.map(($,B)=>Pa(mAA,{children:[B>0&&Pa("br",{},void 0,!1,void 0,this),$.split(mCw).map((X,Y)=>{if(X.length>=3&&X.startsWith("*")&&X.endsWith("*"))return Pa("span",{className:Q,children:X.slice(1,-1)},Y,!1,void 0,this);return Pa(mAA,{children:X},Y,!1,void 0,this)})]},B,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as MZ,Fragment as aCw}from"preact/jsx-dev-runtime";var uCw="italic text-accent font-normal",cCw="You are here",lCw={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},pCw={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},iCw={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},dCw="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",nCw="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",rCw="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",oCw="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",sCw=({card:A})=>{let Q=A.linkLabel===cCw,w=A.linkHref.trim().length===0,$=MZ(aCw,{children:[MZ(X92,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),MZ("span",{className:`${dCw} ${lCw[A.suffix]}`,children:A.title},void 0,!1,void 0,this),MZ("p",{className:nCw,children:A.body},void 0,!1,void 0,this),Q?MZ("span",{className:oCw,children:A.linkLabel},void 0,!1,void 0,this):MZ("span",{className:rCw,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?pCw[A.suffix]:"border-white/10"}`;return Q||w?MZ("div",{className:B,children:$},void 0,!1,void 0,this):MZ("a",{href:A.linkHref,className:`${B} text-inherit no-underline transition-colors ${iCw[A.suffix]}`,children:$},void 0,!1,void 0,this)},Z92=({eyebrow:A,headline:Q,cards:w})=>MZ(B92,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[MZ("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[MZ("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),MZ("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:Y92(Q,uCw)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),MZ("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(($)=>MZ(sCw,{card:$},$.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);fA();var uAA=s1({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:_a,formatter:{parse:JW0,format:$92},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:Z92}});var f92={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.
|
|
10206
|
+
`);return Pa(mAA,{children:w.map(($,B)=>Pa(mAA,{children:[B>0&&Pa("br",{},void 0,!1,void 0,this),$.split(mCw).map((X,Y)=>{if(X.length>=3&&X.startsWith("*")&&X.endsWith("*"))return Pa("span",{className:Q,children:X.slice(1,-1)},Y,!1,void 0,this);return Pa(mAA,{children:X},Y,!1,void 0,this)})]},B,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as MZ,Fragment as aCw}from"preact/jsx-dev-runtime";var uCw="italic text-accent font-normal",cCw="You are here",lCw={work:"text-accent",foundation:"text-secondary",ai:"text-accent-bright"},pCw={work:"border-t-accent/60",foundation:"border-t-secondary/60",ai:"border-t-accent-bright/60"},iCw={work:"hover:border-t-accent",foundation:"hover:border-t-secondary",ai:"hover:border-t-accent-bright"},dCw="font-label text-[10.5px] uppercase tracking-[0.26em] mt-1",nCw="font-body text-[15px] leading-[1.6] text-theme-muted mt-2",rCw="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",oCw="font-label text-[10.5px] uppercase tracking-[0.22em] text-accent self-start mt-[18px] pb-1",sCw=({card:A})=>{let Q=A.linkLabel===cCw,w=A.linkHref.trim().length===0,$=MZ(aCw,{children:[MZ(X92,{brandSuffix:A.suffix,className:"text-[clamp(28px,3vw,40px)] [font-variation-settings:'opsz'_96]"},void 0,!1,void 0,this),MZ("span",{className:`${dCw} ${lCw[A.suffix]}`,children:A.title},void 0,!1,void 0,this),MZ("p",{className:nCw,children:A.body},void 0,!1,void 0,this),Q?MZ("span",{className:oCw,children:A.linkLabel},void 0,!1,void 0,this):MZ("span",{className:rCw,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?pCw[A.suffix]:"border-white/10"}`;return Q||w?MZ("div",{className:B,children:$},void 0,!1,void 0,this):MZ("a",{href:A.linkHref,className:`${B} text-inherit no-underline transition-colors ${iCw[A.suffix]}`,children:$},void 0,!1,void 0,this)},Z92=({eyebrow:A,headline:Q,cards:w})=>MZ(B92,{id:"ecosystem",className:"pt-[112px] pb-[144px] border-t border-white/5",children:[MZ("div",{className:"mx-auto mb-[88px] max-w-[1180px] text-center",children:[MZ("span",{className:"font-label text-[11px] font-semibold uppercase tracking-[0.24em] text-accent",children:A},void 0,!1,void 0,this),MZ("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:Y92(Q,uCw)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),MZ("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(($)=>MZ(sCw,{card:$},$.suffix,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this);fA();var uAA=s1({name:"ecosystem",description:"Rizom ecosystem sibling-site section",schema:_a,formatter:{parse:JW0,format:$92},dataSourceId:"rizom-ecosystem:entities",requiredPermission:"public",layout:{component:Z92}});var f92={name:"@brains/rizom-ecosystem",version:"0.2.0-alpha.169",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 eCw=f.object({}).catchall(f.unknown()).transform(()=>({})),Ayw="ecosystem-section";class cAA extends fw{entityType=Ayw;schema=Na;adapter=TAA;constructor(A={}){super("rizom-ecosystem",f92,A,eCw)}getTemplates(){return{ecosystem:uAA}}getDataSources(){return[new FW0]}}function hM(A={}){return new cAA(A)}C0();fA();fA();k2();C0();H5();C0();fA();var c$="agent",H92="agent-discovery";var W92="agent-network",K92="AgentNetworkWidget",U92="agent-proximity",G92="AgentProximityWidget",Ma="agent-discovery:entities",bW0="agent-discovery:proximity-map",lAA="proximity-map",pAA="agent-list",iAA="agent-detail",sB="skill",D92="skill",LW0="skill-derivation",q92="skill:project",z92="skill-derivation",V92="skill:skill-derivation",J92="skills";var kW0=f.object({name:f.string(),description:f.string(),tags:f.array(f.string())}),EL=f.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),F92=f.enum(["discovered","approved","archived"]).describe("Discovered for review, approved for calling, or archived"),Qyw=f.enum(["professional","team","collective"]),VG=f.object({name:f.string(),kind:Qyw,organization:f.string().optional(),brainName:f.string().describe("Name of the brain instance"),url:f.string().url().describe("Brain endpoint URL"),did:f.string().optional().describe("Decentralized identifier (public)"),repoDid:f.string().optional().describe("ATProto repo DID"),brainDid:f.string().optional().describe("ATProto brain DID"),anchorDid:f.string().optional().describe("ATProto anchor DID"),cardUri:f.string().optional().describe("ATProto brain card URI"),cardCid:f.string().optional().describe("ATProto brain card CID"),a2aEndpoint:f.string().url().optional().describe("A2A endpoint URL"),status:EL,discoveredAt:f.string().datetime().describe("When this agent was first discovered")}),I92=f.object({name:f.string(),url:f.string().url(),status:EL,discoveredAt:f.string().datetime().optional(),slug:f.string(),repoDid:f.string().optional(),brainDid:f.string().optional(),anchorDid:f.string().optional(),cardUri:f.string().optional(),cardCid:f.string().optional(),a2aEndpoint:f.string().url().optional()}),wyw=f.object({name:f.string(),kind:f.enum(["professional","team","collective"]),organization:f.string().optional(),brainName:f.string(),url:f.string().url(),did:f.string().optional(),repoDid:f.string().optional(),brainDid:f.string().optional(),anchorDid:f.string().optional(),cardUri:f.string().optional(),cardCid:f.string().optional(),a2aEndpoint:f.string().url().optional(),status:F92,discoveredAt:f.string().datetime()}),$yw=f.object({name:f.string(),url:f.string().url(),status:F92,discoveredAt:f.string().datetime().optional(),slug:f.string(),repoDid:f.string().optional(),brainDid:f.string().optional(),anchorDid:f.string().optional(),cardUri:f.string().optional(),cardCid:f.string().optional(),a2aEndpoint:f.string().url().optional()}),Oa=d8.extend({entityType:f.literal(c$),metadata:I92}),Byw=TQ.extend({entityType:f.literal(c$),metadata:$yw}),xa=Byw.extend({frontmatter:wyw,about:f.string(),skills:f.array(kW0),notes:f.string()}),Xyw=xa.extend({url:f.string().optional(),typeLabel:f.string().optional()}),Yyw=xa.extend({url:f.string(),typeLabel:f.string()});C0();var Zyw=f.array(kW0);function b92(A){let Q=Zyw.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(`
|
|
10207
10207
|
`)}function L92(A){if(!A.trim())return[];let Q=[];for(let w of A.split(`
|
|
10208
10208
|
`)){let $=w.match(/^- (.+?): (.+?)(?:\s+\[(.+?)\])?$/);if(!$)continue;let B=$[1]??"",X=$[2]??"",Y=$[3],Z=Y?Y.split(",").map((H)=>H.trim()).filter(Boolean):[];Q.push({name:B,description:X,tags:Z})}return Q}var fyw=f.object({name:f.string(),description:f.string(),tags:f.array(f.string())}),Hyw=f.object({about:f.string(),skills:f.array(fyw),notes:f.string()}),k92=new Y6(Hyw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:b92,parser:L92},{key:"notes",label:"Notes",type:"string"}]});class g7 extends r2{constructor(){super({entityType:c$,purpose:"A saved remote peer-brain contact in the local agent directory.",schema:Oa,frontmatterSchema:VG})}fromMarkdown(A){let Q=this.parseFrontMatter(A,VG),w=Ex(Q.url);return{content:A,entityType:c$,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:EL.parse(A.status),discoveredAt:A.discoveredAt},w=k92.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=k92.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,VG),body:this.parseAgentContent(A.content)}}}fA();C0();var Wyw=new g7,_92=f.enum(["discovered","approved","archived"]),Kyw=f.looseObject({id:f.string().optional(),limit:f.number().optional(),page:f.number().optional(),pageSize:f.number().optional(),baseUrl:f.string().optional(),status:_92.optional()}),Uyw=f.looseObject({entityType:f.string().optional(),query:Kyw.optional()});function Gyw(A){let Q=BQ(A.content,VG),w=Wyw.parseAgentContent(A.content);return xa.parse({...A,frontmatter:Q.metadata,about:w.about,skills:w.skills,notes:w.notes})}class _W0 extends i5{id=Ma;name="Agent Directory DataSource";description="Fetches and transforms agent entities for rendering";config={entityType:c$,defaultSort:[{field:"discoveredAt",direction:"desc"}],defaultLimit:50,lookupField:"slug",enableNavigation:!0};constructor(A){super(A)}transformEntity(A){return Gyw(A)}buildDetailResult(A,Q){return{agent:A,prevAgent:Q?.prev??null,nextAgent:Q?.next??null}}parseQuery(A){let Q=Uyw.parse(A);return{entityType:Q.entityType??this.config.entityType,query:Q.query??{}}}buildListResult(A,Q,w){let $=_92.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 Dyw=180*(3-Math.sqrt(5));function N92(A){return Math.max(0,Math.min(1,A))}function j92(A,Q){let[w,$]=A;if(Math.hypot(w,$)<=0.000000000001)return Q*Dyw%360;return(Math.atan2($,w)*180/Math.PI%360+360)%360}function P92(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=[],H=[Y];B.add(Y);while(H.length>0){let W=H.pop();if(!W)continue;Z.push(W);for(let K of Array.from($.get(W)??[]).sort()){if(B.has(K))continue;B.add(K),H.push(K)}}if(Z.length>=2)X.push(Z.sort())}return X.map((Y)=>({label:qyw(Y,w),memberIds:Y,links:Y.flatMap((Z)=>Array.from($.get(Z)??[]).filter((H)=>Z.localeCompare(H)<0).sort().map((H)=>({sourceId:Z,targetId:H})))})).sort((Y,Z)=>{let H=Y.memberIds.some((U)=>(w.get(U)?.tags.length??0)>0),W=Z.memberIds.some((U)=>(w.get(U)?.tags.length??0)>0);if(H!==W)return H?-1:1;let K=Y.label.localeCompare(Z.label);return K!==0?K:(Y.memberIds[0]??"").localeCompare(Z.memberIds[0]??"")})}function qyw(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}`}C0();var zyw=VG.shape.kind,Vyw=f.object({kind:f.enum(["identity","centroid"])}),Jyw=f.object({id:f.string(),name:f.string(),kind:zyw,status:EL,tags:f.array(f.string()),distance:f.number().min(0).max(1),bearing:f.number().min(0).lt(360)}),Fyw=f.object({sourceId:f.string(),targetId:f.string()}),Iyw=f.object({label:f.string(),memberIds:f.array(f.string()).min(2),links:f.array(Fyw).min(1)}),byw=f.object({min:f.number().min(0),max:f.number().min(0)}),M92=f.object({kicker:f.string().optional(),headingLead:f.string().optional(),headingAccent:f.string().optional(),lede:f.string().optional(),ctaLabel:f.string().optional(),ctaHref:f.string().optional()}),fJ=f.object({center:Vyw,nodes:f.array(Jyw),clusters:f.array(Iyw),distanceRange:byw,pendingCount:f.number().int().min(0),kicker:f.string().optional(),headingLead:f.string().optional(),headingAccent:f.string().optional(),lede:f.string().optional(),ctaLabel:f.string().optional(),ctaHref:f.string().optional()});var Lyw=new g7;function O92(A){return A.trim().toLowerCase().replace(/[_\s]+/g,"-")}function rq(A){let Q=new Set,w=[];for(let $ of A){let B=O92($);if(!B||Q.has(B))continue;Q.add(B),w.push(B)}return w}function kyw(A,Q){if(Q.count!==A.count)return Q.count-A.count;return A.tag.localeCompare(Q.tag)}async function x92(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:sB,options:{filter:{visibilityScope:B}}}),A.entityService.listEntities({entityType:c$,options:{filter:{visibilityScope:B}}})]),H=(W)=>{for(let K of rq(W))X.set(K,(X.get(K)??0)+1)};for(let W of Y)H(W.metadata.tags);for(let W of Z){let K=Lyw.parseAgentContent(W.content);H(K.skills.flatMap((U)=>U.tags))}return Array.from(X.entries()).map(([W,K])=>({tag:W,count:K})).filter((W)=>W.count>=w).sort(kyw).slice(0,$)}function R92(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(`
|
|
10209
10209
|
`)}var _yw={entityId:"brain-character",entityType:"brain-character"},Nyw=0.25,jyw=new g7;async function NW0(A){let[Q,w]=await Promise.all([A.entityService.listEntities({entityType:c$}),A.semantic.project({types:[c$],origin:_yw,maxNeighborDistance:Nyw})]),$=new Map(w.points.filter((Y)=>Y.entityType===c$).map((Y)=>[Y.entityId,Y])),B=[];for(let Y of Q.slice().sort((Z,H)=>Z.id.localeCompare(H.id))){let Z=$.get(Y.id);if(!Z)continue;let{frontmatter:H,body:W}=jyw.parseEntity(Y);B.push({id:Y.id,name:H.name,kind:H.kind,status:H.status,tags:rq(W.skills.flatMap((K)=>K.tags)),distance:N92(Z.distanceToOrigin),bearing:j92(Z.coordinates,B.length)})}let X=B.filter((Y)=>Y.status!=="archived");return fJ.parse({center:{kind:w.origin.kind==="entity"?"identity":"centroid"},nodes:B,clusters:P92(X,w.neighbors),distanceRange:w.distanceRange,pendingCount:Math.max(0,Q.length-B.length)})}class jW0{id=bW0;name="Agent Proximity Map DataSource";description="Builds a public semantic proximity map for saved agents";async fetch(A,Q,w){let $=await NW0({entityService:w.entityService,semantic:{project:(B)=>w.entityService.projectSemanticSpace(B)}});return Q.parse($)}}fA();C0();Q$();fA();async function PW0(A,Q){let $=`${(A.startsWith("http")?A:`https://${A}`).replace(/\/$/,"")}/.well-known/agent-card.json`;try{let B=await Q($);if(!B.ok)return null;let X=await B.json();return au(X)}catch{return null}}function CM(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""}k2();var Pyw=new g7;function MW0(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:Pyw.createAgentContent({name:w,kind:$,...A.anchor?.organization&&{organization:A.anchor.organization},brainName:A.brainName,url:A.url,status:X,discoveredAt:Y,about:B.join(`
|
|
@@ -10724,7 +10724,7 @@ ${A.guidance}`:B}}function C52(A){return{...A,evidence:A.evidence.map((Q)=>({...
|
|
|
10724
10724
|
/* the shimmer delay is inlined per node, so the override needs force */
|
|
10725
10725
|
.agent-proximity-site .proximity-agent { animation: none !important; }
|
|
10726
10726
|
}
|
|
10727
|
-
`,XT={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 tAA(A){let Q=A.nodes.filter((W)=>W.status!=="archived").length,w=A.nodes.length-Q,$=A.kicker??XT.kicker,B=A.headingLead??XT.headingLead,X=A.headingAccent??XT.headingAccent,Y=A.lede??XT.lede,Z=A.ctaLabel??XT.ctaLabel,H=A.ctaHref??XT.ctaHref;return a6("section",{class:"agent-proximity-site","aria-label":"Agent proximity map",children:[a6("style",{children:Dgw},void 0,!1,void 0,this),a6("div",{class:"agent-proximity-site__grid",children:[a6("div",{class:"agent-proximity-site__copy",children:[a6("p",{class:"agent-proximity-site__kicker",children:$},void 0,!1,void 0,this),a6("h2",{class:"agent-proximity-site__heading",children:[B," ",a6("em",{children:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a6("p",{class:"agent-proximity-site__lede",children:Y},void 0,!1,void 0,this),a6("div",{class:"agent-proximity-site__stats","aria-label":"Network summary",children:[a6("div",{children:[a6("div",{class:"agent-proximity-site__stat-number",children:Q},void 0,!1,void 0,this),a6("div",{class:"agent-proximity-site__stat-label",children:"agents"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a6("div",{children:[a6("div",{class:"agent-proximity-site__stat-number",children:A.clusters.length},void 0,!1,void 0,this),a6("div",{class:"agent-proximity-site__stat-label",children:"constellations"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a6("div",{children:[a6("div",{class:"agent-proximity-site__stat-number",children:w},void 0,!1,void 0,this),a6("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),a6("a",{class:"agent-proximity-site__cta",href:H,children:Z},void 0,!1,void 0,this),A.pendingCount>0&&a6("p",{class:"agent-proximity-site__note",children:[A.pendingCount," pending semantic indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&a6("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),a6("div",{class:"agent-proximity-site__map",children:a6(hW0,{data:A,surface:"site"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a6("div",{class:"agent-proximity-site__legend","aria-label":"Agent kinds",children:[a6("span",{children:[a6("b",{children:"\u25CF"},void 0,!1,void 0,this)," professional"]},void 0,!0,void 0,this),a6("span",{children:[a6("b",{children:"\u2234"},void 0,!1,void 0,this)," team"]},void 0,!0,void 0,this),a6("span",{children:[a6("b",{children:"\u25CC"},void 0,!1,void 0,this)," collective"]},void 0,!0,void 0,this),a6("span",{children:[a6("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 qgw=f.union([f.enum(["public","shared","restricted"]),f.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),zgw=f.object({currentPage:f.number(),totalPages:f.number(),totalItems:f.number(),pageSize:f.number(),hasNextPage:f.boolean(),hasPrevPage:f.boolean()}),Vgw=f.object({name:f.string(),description:f.string(),tags:f.array(f.string())}),eAA=f.enum(["discovered","approved","archived"]),Jgw=f.enum(["professional","team","collective"]),Fgw=f.object({name:f.string(),kind:Jgw,organization:f.string().optional(),brainName:f.string(),url:f.url(),did:f.string().optional(),repoDid:f.string().optional(),brainDid:f.string().optional(),anchorDid:f.string().optional(),cardUri:f.string().optional(),cardCid:f.string().optional(),a2aEndpoint:f.url().optional(),status:eAA,discoveredAt:f.string()}),Igw=f.object({name:f.string(),url:f.url(),status:eAA,discoveredAt:f.string().optional(),slug:f.string(),repoDid:f.string().optional(),brainDid:f.string().optional(),anchorDid:f.string().optional(),cardUri:f.string().optional(),cardCid:f.string().optional(),a2aEndpoint:f.url().optional()}),TW0=f.object({id:f.string(),entityType:f.literal(c$),content:f.string(),created:f.string(),updated:f.string(),visibility:qgw,metadata:Igw,contentHash:f.string(),frontmatter:Fgw,about:f.string(),skills:f.array(Vgw),notes:f.string(),url:f.string().optional(),typeLabel:f.string().optional()}),bgw=f.object({agents:f.array(TW0),pageTitle:f.string().optional(),pagination:zgw.nullable(),baseUrl:f.string().optional(),selectedStatus:f.union([f.literal("all"),eAA])}),o92="/scripts/agent-proximity-map.js",Lgw=new Y6(M92,{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 s92(){return{[lAA]:s1({name:lAA,description:"Semantic agent proximity map site section",schema:fJ,dataSourceId:bW0,overlayFormatter:Lgw,requiredPermission:"public",runtimeScripts:[{src:o92,defer:!0}],staticAssets:{[o92]:BT},layout:{component:tAA}}),[pAA]:s1({name:pAA,description:"Agent directory list page template",schema:bgw,dataSourceId:Ma,requiredPermission:"public",layout:{component:n92}}),[iAA]:s1({name:iAA,description:"Individual agent profile template",schema:f.object({agent:TW0,prevAgent:TW0.nullable(),nextAgent:TW0.nullable()}),dataSourceId:Ma,requiredPermission:"public",layout:{component:r92}})}}var YT={name:"@brains/agent-discovery",version:"0.2.0-alpha.168",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 _gw=new g7;class A1A extends fw{entityType=c$;schema=Oa;adapter=_gw;constructor(){super(H92,YT,{},o7)}createGenerationHandler(A){return new dAA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return s92()}getDataSources(){return[new _W0(this.logger.child("AgentDataSource")),new jW0]}async onRegister(A){l92(A),u92(A,this.id)}async getInstructions(){return p92()}}function Q1A(){return new A1A}fA();C0();M9();C0();var a92=f.object({source:f.object({kind:f.literal("url"),url:f.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:f.boolean().optional(),confirmationToken:f.string().optional()}),Ngw=new g7;function jgw(A){let Q=CM(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function Pgw(A,Q){return(CM(Q)||A).toLowerCase()}async function Mgw(A){let{context:Q,entityId:w,card:$}=A,B=new Date().toISOString(),X=await Q.entityService.getEntity({entityType:c$,id:w}),Y=MW0($,{status:"approved"}),H={...Ngw.fromMarkdown(Y.content).metadata,...Y.metadata,a2aEndpoint:$.url};if(X){let K={...X,content:Y.content,metadata:H,updated:B};return await Q.entityService.updateEntity({entity:K}),{entity:K,created:!1}}let W={id:w,entityType:c$,content:Y.content,metadata:H,contentHash:"",visibility:"public",created:B,updated:B};return await Q.entityService.createEntity({entity:W}),{entity:W,created:!0}}function t92(A,Q=globalThis.fetch){let $=new Gf;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:a92.shape,visibility:"trusted",sideEffects:"external",handler:async(B,X)=>{let Y=a92.safeParse(B);if(!Y.success)return{success:!1,error:`Invalid input: ${Y.error.issues.map((K)=>`${K.path.join(".")}: ${K.message}`).join(", ")}`};let Z=Y.data,H=jgw(Z.source.url);if(!H)return{success:!1,error:"Provide a valid remote agent domain or URL to connect.",code:"invalid_agent_url"};try{A.permissions.assertEntityActionAllowed(c$,"create",X)}catch(K){return{success:!1,error:K instanceof Error?K.message:String(K)}}if(Z.confirmed){let K=Z.confirmationToken,U=$.validate(K,Z);if(U.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(U.status==="mismatch")return{success:!1,error:"Confirmed agent connection arguments do not match the pending approval. Please request connection again and confirm the new approval."};let G=await PW0(H.fetchTarget,Q);if(!G)return{success:!1,error:`Could not verify an A2A Agent Card for ${H.domain}.`,code:"not_an_agent"};let q=Pgw(H.domain,G.url),{entity:V,created:J}=await Mgw({context:A,entityId:q,sourceUrl:Z.source.url,card:G});return{success:!0,data:{status:V.metadata.status,entityId:V.id,connected:!0,created:J,a2aEndpoint:G.url,skills:G.skills.map((F)=>({name:F.name,description:F.description,tags:F.tags}))}}}let W=$.create((K)=>({source:Z.source,confirmed:!0,confirmationToken:K}));return{needsConfirmation:!0,toolName:"agent_connect",summary:`Verify and connect agent ${H.domain}?`,preview:`This will fetch and validate ${H.domain}'s A2A Agent Card, then save the verified contact as approved for future outbound calls. It will not message the remote agent or grant it inbound trusted access.`,args:W}}}}M9();C0();var Ogw=f.enum(["public","trusted"]),e92=f.object({agent:f.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:Ogw.describe("Inbound A2A trust level. Use trusted to grant trusted inbound access, public to revoke it."),confirmed:f.boolean().optional(),confirmationToken:f.string().optional(),keyFingerprint:f.string().optional()}),xgw=f.object({keys:f.array(f.unknown())}),Rgw=f.object({kty:f.literal("OKP"),crv:f.literal("Ed25519"),x:f.string(),kid:f.string().optional(),alg:f.literal("EdDSA").optional()}).passthrough();function A72(A){return(CM(A)||A.trim()).toLowerCase()}async function vgw(A,Q){let w=A72(Q),$=await A.entityService.getEntity({entityType:c$,id:w});if(!$)return null;let B=A72($.metadata.a2aEndpoint??$.metadata.url);if(!B)return null;return{domain:B}}async function hgw(A,Q){try{let w=await Q(`https://${A}/.well-known/jwks.json`);if(!w.ok)return null;let $=xgw.safeParse(await w.json());if(!$.success)return null;let B=$.data.keys.map((X)=>Rgw.safeParse(X)).find((X)=>X.success);if(!B?.success)return null;return tp0(B.data)}catch{return null}}function Q72(A,Q=globalThis.fetch){let $=new Gf;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:e92.shape,visibility:"anchor",sideEffects:"external",handler:async(B)=>{let X=e92.safeParse(B);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.issues.map((G)=>`${G.path.join(".")}: ${G.message}`).join(", ")}`};let Y=A4();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let Z=await vgw(A,X.data.agent);if(!Z)return{success:!1,error:`No saved agent contact found for ${X.data.agent}. Connect the agent before setting inbound trust.`,code:"agent_not_found"};let H=X.data;if(H.confirmed){let G=$.validate(H.confirmationToken,H);if(G.status==="missing")return{success:!1,error:"No pending agent trust confirmation found. Please request the trust change again and confirm the new approval."};if(G.status==="mismatch")return{success:!1,error:"Confirmed agent trust arguments do not match the pending approval. Please request the trust change again and confirm the new approval."};if(H.level==="trusted"){if(!H.keyFingerprint)return{success:!1,error:"Missing key fingerprint for trusted A2A grant."};let q=await Y.grantA2APeerTrust({domain:Z.domain,keyFingerprint:H.keyFingerprint,grantedLevel:"trusted"});return{success:!0,data:{agent:Z.domain,level:q.grantedLevel,keyFingerprint:q.keyFingerprint}}}return await Y.revokeA2APeerTrust(Z.domain),{success:!0,data:{agent:Z.domain,level:"public"}}}let W=H.level==="trusted"?await hgw(Z.domain,Q):void 0;if(H.level==="trusted"&&!W)return{success:!1,error:`Could not fetch an A2A signing key from ${Z.domain}.`,code:"jwks_unavailable"};let K=$.create((G)=>({agent:Z.domain,level:H.level,confirmed:!0,confirmationToken:G,...W?{keyFingerprint:W}:{}})),U=H.level==="trusted";return{needsConfirmation:!0,toolName:"agent_set_trust_level",summary:U?`Grant inbound trusted A2A access to ${Z.domain}?`:`Revoke inbound trusted A2A access from ${Z.domain}?`,preview:U?`This will grant inbound trusted A2A access to ${Z.domain} and pin key fingerprint ${W}. 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:K}}}}var Cgw=f.object({}).strict();class w1A extends Uw{fetchFn;constructor(A){super("agent",YT,{},Cgw);this.fetchFn=A}async getTools(){return[t92(this.getContext(),this.fetchFn),Q72(this.getContext(),this.fetchFn)]}}function $1A(){return new w1A}fA();fA();C0();var yM=f.object({name:f.string(),description:f.string(),tags:f.array(f.string()),examples:f.array(f.string())}),w72=yM,Ca=d8.extend({entityType:f.literal(sB),metadata:w72});fA();class ZT extends r2{constructor(){super({entityType:sB,purpose:"A capability advertised by a remote agent.",schema:Ca,frontmatterSchema:yM})}fromMarkdown(A){let Q=this.parseFrontMatter(A,yM);return{content:A,entityType:sB,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}fA();C0();var ygw=f.object({skills:f.array(yM).max(8)}),$72=s1({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:ygw,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
|
|
10727
|
+
`,XT={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 tAA(A){let Q=A.nodes.filter((W)=>W.status!=="archived").length,w=A.nodes.length-Q,$=A.kicker??XT.kicker,B=A.headingLead??XT.headingLead,X=A.headingAccent??XT.headingAccent,Y=A.lede??XT.lede,Z=A.ctaLabel??XT.ctaLabel,H=A.ctaHref??XT.ctaHref;return a6("section",{class:"agent-proximity-site","aria-label":"Agent proximity map",children:[a6("style",{children:Dgw},void 0,!1,void 0,this),a6("div",{class:"agent-proximity-site__grid",children:[a6("div",{class:"agent-proximity-site__copy",children:[a6("p",{class:"agent-proximity-site__kicker",children:$},void 0,!1,void 0,this),a6("h2",{class:"agent-proximity-site__heading",children:[B," ",a6("em",{children:X},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a6("p",{class:"agent-proximity-site__lede",children:Y},void 0,!1,void 0,this),a6("div",{class:"agent-proximity-site__stats","aria-label":"Network summary",children:[a6("div",{children:[a6("div",{class:"agent-proximity-site__stat-number",children:Q},void 0,!1,void 0,this),a6("div",{class:"agent-proximity-site__stat-label",children:"agents"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a6("div",{children:[a6("div",{class:"agent-proximity-site__stat-number",children:A.clusters.length},void 0,!1,void 0,this),a6("div",{class:"agent-proximity-site__stat-label",children:"constellations"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a6("div",{children:[a6("div",{class:"agent-proximity-site__stat-number",children:w},void 0,!1,void 0,this),a6("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),a6("a",{class:"agent-proximity-site__cta",href:H,children:Z},void 0,!1,void 0,this),A.pendingCount>0&&a6("p",{class:"agent-proximity-site__note",children:[A.pendingCount," pending semantic indexing"]},void 0,!0,void 0,this),A.center.kind==="centroid"&&a6("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),a6("div",{class:"agent-proximity-site__map",children:a6(hW0,{data:A,surface:"site"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),a6("div",{class:"agent-proximity-site__legend","aria-label":"Agent kinds",children:[a6("span",{children:[a6("b",{children:"\u25CF"},void 0,!1,void 0,this)," professional"]},void 0,!0,void 0,this),a6("span",{children:[a6("b",{children:"\u2234"},void 0,!1,void 0,this)," team"]},void 0,!0,void 0,this),a6("span",{children:[a6("b",{children:"\u25CC"},void 0,!1,void 0,this)," collective"]},void 0,!0,void 0,this),a6("span",{children:[a6("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 qgw=f.union([f.enum(["public","shared","restricted"]),f.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),zgw=f.object({currentPage:f.number(),totalPages:f.number(),totalItems:f.number(),pageSize:f.number(),hasNextPage:f.boolean(),hasPrevPage:f.boolean()}),Vgw=f.object({name:f.string(),description:f.string(),tags:f.array(f.string())}),eAA=f.enum(["discovered","approved","archived"]),Jgw=f.enum(["professional","team","collective"]),Fgw=f.object({name:f.string(),kind:Jgw,organization:f.string().optional(),brainName:f.string(),url:f.url(),did:f.string().optional(),repoDid:f.string().optional(),brainDid:f.string().optional(),anchorDid:f.string().optional(),cardUri:f.string().optional(),cardCid:f.string().optional(),a2aEndpoint:f.url().optional(),status:eAA,discoveredAt:f.string()}),Igw=f.object({name:f.string(),url:f.url(),status:eAA,discoveredAt:f.string().optional(),slug:f.string(),repoDid:f.string().optional(),brainDid:f.string().optional(),anchorDid:f.string().optional(),cardUri:f.string().optional(),cardCid:f.string().optional(),a2aEndpoint:f.url().optional()}),TW0=f.object({id:f.string(),entityType:f.literal(c$),content:f.string(),created:f.string(),updated:f.string(),visibility:qgw,metadata:Igw,contentHash:f.string(),frontmatter:Fgw,about:f.string(),skills:f.array(Vgw),notes:f.string(),url:f.string().optional(),typeLabel:f.string().optional()}),bgw=f.object({agents:f.array(TW0),pageTitle:f.string().optional(),pagination:zgw.nullable(),baseUrl:f.string().optional(),selectedStatus:f.union([f.literal("all"),eAA])}),o92="/scripts/agent-proximity-map.js",Lgw=new Y6(M92,{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 s92(){return{[lAA]:s1({name:lAA,description:"Semantic agent proximity map site section",schema:fJ,dataSourceId:bW0,overlayFormatter:Lgw,requiredPermission:"public",runtimeScripts:[{src:o92,defer:!0}],staticAssets:{[o92]:BT},layout:{component:tAA}}),[pAA]:s1({name:pAA,description:"Agent directory list page template",schema:bgw,dataSourceId:Ma,requiredPermission:"public",layout:{component:n92}}),[iAA]:s1({name:iAA,description:"Individual agent profile template",schema:f.object({agent:TW0,prevAgent:TW0.nullable(),nextAgent:TW0.nullable()}),dataSourceId:Ma,requiredPermission:"public",layout:{component:r92}})}}var YT={name:"@brains/agent-discovery",version:"0.2.0-alpha.169",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 _gw=new g7;class A1A extends fw{entityType=c$;schema=Oa;adapter=_gw;constructor(){super(H92,YT,{},o7)}createGenerationHandler(A){return new dAA(this.logger.child("AgentGenerationJobHandler"),A)}getTemplates(){return s92()}getDataSources(){return[new _W0(this.logger.child("AgentDataSource")),new jW0]}async onRegister(A){l92(A),u92(A,this.id)}async getInstructions(){return p92()}}function Q1A(){return new A1A}fA();C0();M9();C0();var a92=f.object({source:f.object({kind:f.literal("url"),url:f.string().min(1).describe("Remote agent domain or URL to verify and connect. Preserve bare domains as bare domains.")}),confirmed:f.boolean().optional(),confirmationToken:f.string().optional()}),Ngw=new g7;function jgw(A){let Q=CM(A);if(!Q)return null;return{domain:Q,fetchTarget:A.trim().startsWith("http")?A.trim():Q}}function Pgw(A,Q){return(CM(Q)||A).toLowerCase()}async function Mgw(A){let{context:Q,entityId:w,card:$}=A,B=new Date().toISOString(),X=await Q.entityService.getEntity({entityType:c$,id:w}),Y=MW0($,{status:"approved"}),H={...Ngw.fromMarkdown(Y.content).metadata,...Y.metadata,a2aEndpoint:$.url};if(X){let K={...X,content:Y.content,metadata:H,updated:B};return await Q.entityService.updateEntity({entity:K}),{entity:K,created:!1}}let W={id:w,entityType:c$,content:Y.content,metadata:H,contentHash:"",visibility:"public",created:B,updated:B};return await Q.entityService.createEntity({entity:W}),{entity:W,created:!0}}function t92(A,Q=globalThis.fetch){let $=new Gf;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:a92.shape,visibility:"trusted",sideEffects:"external",handler:async(B,X)=>{let Y=a92.safeParse(B);if(!Y.success)return{success:!1,error:`Invalid input: ${Y.error.issues.map((K)=>`${K.path.join(".")}: ${K.message}`).join(", ")}`};let Z=Y.data,H=jgw(Z.source.url);if(!H)return{success:!1,error:"Provide a valid remote agent domain or URL to connect.",code:"invalid_agent_url"};try{A.permissions.assertEntityActionAllowed(c$,"create",X)}catch(K){return{success:!1,error:K instanceof Error?K.message:String(K)}}if(Z.confirmed){let K=Z.confirmationToken,U=$.validate(K,Z);if(U.status==="missing")return{success:!1,error:"No pending agent connection confirmation found. Please request connection again and confirm the new approval."};if(U.status==="mismatch")return{success:!1,error:"Confirmed agent connection arguments do not match the pending approval. Please request connection again and confirm the new approval."};let G=await PW0(H.fetchTarget,Q);if(!G)return{success:!1,error:`Could not verify an A2A Agent Card for ${H.domain}.`,code:"not_an_agent"};let q=Pgw(H.domain,G.url),{entity:V,created:J}=await Mgw({context:A,entityId:q,sourceUrl:Z.source.url,card:G});return{success:!0,data:{status:V.metadata.status,entityId:V.id,connected:!0,created:J,a2aEndpoint:G.url,skills:G.skills.map((F)=>({name:F.name,description:F.description,tags:F.tags}))}}}let W=$.create((K)=>({source:Z.source,confirmed:!0,confirmationToken:K}));return{needsConfirmation:!0,toolName:"agent_connect",summary:`Verify and connect agent ${H.domain}?`,preview:`This will fetch and validate ${H.domain}'s A2A Agent Card, then save the verified contact as approved for future outbound calls. It will not message the remote agent or grant it inbound trusted access.`,args:W}}}}M9();C0();var Ogw=f.enum(["public","trusted"]),e92=f.object({agent:f.string().min(1).describe("Saved agent id, domain, or URL whose inbound A2A trust to set."),level:Ogw.describe("Inbound A2A trust level. Use trusted to grant trusted inbound access, public to revoke it."),confirmed:f.boolean().optional(),confirmationToken:f.string().optional(),keyFingerprint:f.string().optional()}),xgw=f.object({keys:f.array(f.unknown())}),Rgw=f.object({kty:f.literal("OKP"),crv:f.literal("Ed25519"),x:f.string(),kid:f.string().optional(),alg:f.literal("EdDSA").optional()}).passthrough();function A72(A){return(CM(A)||A.trim()).toLowerCase()}async function vgw(A,Q){let w=A72(Q),$=await A.entityService.getEntity({entityType:c$,id:w});if(!$)return null;let B=A72($.metadata.a2aEndpoint??$.metadata.url);if(!B)return null;return{domain:B}}async function hgw(A,Q){try{let w=await Q(`https://${A}/.well-known/jwks.json`);if(!w.ok)return null;let $=xgw.safeParse(await w.json());if(!$.success)return null;let B=$.data.keys.map((X)=>Rgw.safeParse(X)).find((X)=>X.success);if(!B?.success)return null;return tp0(B.data)}catch{return null}}function Q72(A,Q=globalThis.fetch){let $=new Gf;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:e92.shape,visibility:"anchor",sideEffects:"external",handler:async(B)=>{let X=e92.safeParse(B);if(!X.success)return{success:!1,error:`Invalid input: ${X.error.issues.map((G)=>`${G.path.join(".")}: ${G.message}`).join(", ")}`};let Y=A4();if(!Y)return{success:!1,error:"Auth service is required to set inbound A2A trust.",code:"auth_service_unavailable"};let Z=await vgw(A,X.data.agent);if(!Z)return{success:!1,error:`No saved agent contact found for ${X.data.agent}. Connect the agent before setting inbound trust.`,code:"agent_not_found"};let H=X.data;if(H.confirmed){let G=$.validate(H.confirmationToken,H);if(G.status==="missing")return{success:!1,error:"No pending agent trust confirmation found. Please request the trust change again and confirm the new approval."};if(G.status==="mismatch")return{success:!1,error:"Confirmed agent trust arguments do not match the pending approval. Please request the trust change again and confirm the new approval."};if(H.level==="trusted"){if(!H.keyFingerprint)return{success:!1,error:"Missing key fingerprint for trusted A2A grant."};let q=await Y.grantA2APeerTrust({domain:Z.domain,keyFingerprint:H.keyFingerprint,grantedLevel:"trusted"});return{success:!0,data:{agent:Z.domain,level:q.grantedLevel,keyFingerprint:q.keyFingerprint}}}return await Y.revokeA2APeerTrust(Z.domain),{success:!0,data:{agent:Z.domain,level:"public"}}}let W=H.level==="trusted"?await hgw(Z.domain,Q):void 0;if(H.level==="trusted"&&!W)return{success:!1,error:`Could not fetch an A2A signing key from ${Z.domain}.`,code:"jwks_unavailable"};let K=$.create((G)=>({agent:Z.domain,level:H.level,confirmed:!0,confirmationToken:G,...W?{keyFingerprint:W}:{}})),U=H.level==="trusted";return{needsConfirmation:!0,toolName:"agent_set_trust_level",summary:U?`Grant inbound trusted A2A access to ${Z.domain}?`:`Revoke inbound trusted A2A access from ${Z.domain}?`,preview:U?`This will grant inbound trusted A2A access to ${Z.domain} and pin key fingerprint ${W}. 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:K}}}}var Cgw=f.object({}).strict();class w1A extends Uw{fetchFn;constructor(A){super("agent",YT,{},Cgw);this.fetchFn=A}async getTools(){return[t92(this.getContext(),this.fetchFn),Q72(this.getContext(),this.fetchFn)]}}function $1A(){return new w1A}fA();fA();C0();var yM=f.object({name:f.string(),description:f.string(),tags:f.array(f.string()),examples:f.array(f.string())}),w72=yM,Ca=d8.extend({entityType:f.literal(sB),metadata:w72});fA();class ZT extends r2{constructor(){super({entityType:sB,purpose:"A capability advertised by a remote agent.",schema:Ca,frontmatterSchema:yM})}fromMarkdown(A){let Q=this.parseFrontMatter(A,yM);return{content:A,entityType:sB,metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}fA();C0();var ygw=f.object({skills:f.array(yM).max(8)}),$72=s1({name:"skill:skill-derivation",description:"Derive skills from topic titles and brain capabilities",dataSourceId:"shell:ai-content",schema:ygw,useKnowledgeContext:!0,basePrompt:`You are analyzing a brain's content to identify its high-level capabilities.
|
|
10728
10728
|
|
|
10729
10729
|
Given knowledge domains, CONSOLIDATE related topics into broader skills.
|
|
10730
10730
|
There should be FEWER skills than topics \u2014 combine related domains.
|
|
@@ -10874,9 +10874,9 @@ Context:
|
|
|
10874
10874
|
${JSON.stringify($,null,2)}
|
|
10875
10875
|
|
|
10876
10876
|
Draft SWOT:
|
|
10877
|
-
${JSON.stringify(w,null,2)}`}function dW0(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function XEw(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 nW0{logger;context;adapter=new HJ;constructor(A,Q){this.logger=A,this.context=Q}validateAndParse(A){let Q=Y1A.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 K1A(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:W}=await this.context.ai.generateObject(await wEw(this.context,$),Z1A),K=Z1A.parse(W);await w.report({progress:0.75,message:"Refining SWOT language"});let U=await this.context.ai.generateObject(await BEw(this.context,$,K),lW0);B=lW0.parse(U.object),XEw(K,B)}let Y=new Date().toISOString(),Z=this.adapter.createSwotContent({strengths:dW0(B.strengths),weaknesses:dW0(B.weaknesses),opportunities:dW0(B.opportunities),threats:dW0(B.threats),derivedAt:Y});await w.report({progress:0.9,message:"Saving SWOT entity"});let H=await this.context.entityService.getEntity({entityType:"swot",id:"swot"});if(H)await this.context.entityService.updateEntity({entity:{...H,content: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"}}}C0();import{jsxDEV as JX}from"preact/jsx-dev-runtime";var rW0=f.object({title:f.string(),detail:f.string().optional()}),YEw=f.discriminatedUnion("status",[f.object({status:f.literal("generating")}),f.object({status:f.literal("ready"),strengths:f.array(rW0).default([]),weaknesses:f.array(rW0).default([]),opportunities:f.array(rW0).default([]),threats:f.array(rW0).default([]),derivedAt:f.string()})]);function ZEw({items:A}){if(A.length===0)return JX("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return JX("ul",{class:"swot-list",children:A.map((Q)=>JX("li",{class:"swot-item",children:[JX("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?JX("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 oW0({title:A,tone:Q,items:w}){return JX("section",{class:`swot-cell is-${Q}`,children:[JX("div",{class:"swot-head",children:A},void 0,!1,void 0,this),JX(ZEw,{items:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function D1A({data:A}){let Q=YEw.safeParse(A);if(!Q.success||Q.data.status==="generating")return JX("div",{"data-swot-widget":!0,children:JX("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let w=Q.data;return JX("div",{"data-swot-widget":!0,children:JX("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[JX(oW0,{title:"Strengths",tone:"s",items:w.strengths},void 0,!1,void 0,this),JX(oW0,{title:"Weaknesses",tone:"w",items:w.weaknesses},void 0,!1,void 0,this),JX(oW0,{title:"Opportunities",tone:"o",items:w.opportunities},void 0,!1,void 0,this),JX(oW0,{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 q1A={name:"@brains/assessment",version:"0.2.0-alpha.
|
|
10877
|
+
${JSON.stringify(w,null,2)}`}function dW0(A){return A.map((Q)=>Q.detail===null?{title:Q.title}:{title:Q.title,detail:Q.detail})}function XEw(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 nW0{logger;context;adapter=new HJ;constructor(A,Q){this.logger=A,this.context=Q}validateAndParse(A){let Q=Y1A.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 K1A(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:W}=await this.context.ai.generateObject(await wEw(this.context,$),Z1A),K=Z1A.parse(W);await w.report({progress:0.75,message:"Refining SWOT language"});let U=await this.context.ai.generateObject(await BEw(this.context,$,K),lW0);B=lW0.parse(U.object),XEw(K,B)}let Y=new Date().toISOString(),Z=this.adapter.createSwotContent({strengths:dW0(B.strengths),weaknesses:dW0(B.weaknesses),opportunities:dW0(B.opportunities),threats:dW0(B.threats),derivedAt:Y});await w.report({progress:0.9,message:"Saving SWOT entity"});let H=await this.context.entityService.getEntity({entityType:"swot",id:"swot"});if(H)await this.context.entityService.updateEntity({entity:{...H,content: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"}}}C0();import{jsxDEV as JX}from"preact/jsx-dev-runtime";var rW0=f.object({title:f.string(),detail:f.string().optional()}),YEw=f.discriminatedUnion("status",[f.object({status:f.literal("generating")}),f.object({status:f.literal("ready"),strengths:f.array(rW0).default([]),weaknesses:f.array(rW0).default([]),opportunities:f.array(rW0).default([]),threats:f.array(rW0).default([]),derivedAt:f.string()})]);function ZEw({items:A}){if(A.length===0)return JX("p",{class:"swot-empty",children:"\u2014"},void 0,!1,void 0,this);return JX("ul",{class:"swot-list",children:A.map((Q)=>JX("li",{class:"swot-item",children:[JX("b",{children:Q.title},void 0,!1,void 0,this),Q.detail?JX("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 oW0({title:A,tone:Q,items:w}){return JX("section",{class:`swot-cell is-${Q}`,children:[JX("div",{class:"swot-head",children:A},void 0,!1,void 0,this),JX(ZEw,{items:w},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function D1A({data:A}){let Q=YEw.safeParse(A);if(!Q.success||Q.data.status==="generating")return JX("div",{"data-swot-widget":!0,children:JX("p",{class:"muted",children:"generating assessment\u2026"},void 0,!1,void 0,this)},void 0,!1,void 0,this);let w=Q.data;return JX("div",{"data-swot-widget":!0,children:JX("div",{class:"swot",role:"grid","aria-label":"SWOT analysis of agent network",children:[JX(oW0,{title:"Strengths",tone:"s",items:w.strengths},void 0,!1,void 0,this),JX(oW0,{title:"Weaknesses",tone:"w",items:w.weaknesses},void 0,!1,void 0,this),JX(oW0,{title:"Opportunities",tone:"o",items:w.opportunities},void 0,!1,void 0,this),JX(oW0,{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 q1A={name:"@brains/assessment",version:"0.2.0-alpha.169",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 HEw=f.object({status:f.enum(["ready","generating"])}),z1A=new HJ;class V1A extends fw{entityType="swot";schema=fT;adapter=z1A;initialSyncComplete=!1;constructor(){super("swot",q1A,{},o7)}async onRegister(A){let Q=new nW0(this.logger.child("SwotDerivationHandler"),A);A.jobs.registerHandler("derive",Q),A.eval.registerHandler("deriveSwot",async()=>{let X=gX.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 z1A.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}=HEw.parse(X);return{digest:[{label:"SWOT",value:Y==="ready"?"Ready":"Generating",tone:Y==="ready"?"good":"warn"}]}},component:D1A,dataProvider:async()=>{let X=await A.entityService.getEntity({entityType:"swot",id:"swot"});if(!X)return{status:"generating"};let{frontmatter:Y}=z1A.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 J1A(){return new V1A}fA();H5();C0();var Pl8=new HJ,V72=f.object({name:f.string(),description:f.string(),tags:f.array(f.string())}),J72=f.enum(["discovered","approved"]),WEw=f.object({name:f.string(),kind:f.enum(["professional","team","collective"]),organization:f.string().optional(),brainName:f.string(),url:f.string().url(),did:f.string().optional(),status:J72,discoveredAt:f.string().datetime()}),KEw=d8.extend({entityType:f.literal("agent"),metadata:f.object({name:f.string(),url:f.string().url(),status:J72,slug:f.string()})}),F1A=f.object({name:f.string(),description:f.string(),tags:f.array(f.string()),examples:f.array(f.string())}),UEw=d8.extend({entityType:f.literal("skill"),metadata:F1A}),GEw=f.object({about:f.string(),skills:f.array(V72),notes:f.string()});function DEw(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(`
|
|
10878
10878
|
`)}function qEw(A){if(!A.trim())return[];return A.split(`
|
|
10879
|
-
`).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 zEw=new Y6(GEw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:DEw,parser:qEw},{key:"notes",label:"Notes",type:"string"}]});class F72 extends r2{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:KEw,frontmatterSchema:WEw})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=zEw.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 I72 extends r2{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:UEw,frontmatterSchema:F1A})}fromMarkdown(A){let Q=this.parseFrontMatter(A,F1A);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var Ml8=new F72,Ol8=new I72,VEw=f.object({name:f.string(),description:f.string(),tags:f.array(f.string()),examples:f.array(f.string())}),xl8=f.object({skills:f.array(VEw),agents:f.array(f.object({id:f.string().optional(),name:f.string(),kind:f.enum(["professional","team","collective"]),organization:f.string().optional(),brainName:f.string(),url:f.url(),did:f.string().optional(),status:f.enum(["discovered","approved"]),discoveredAt:f.string().datetime().optional(),about:f.string(),skills:f.array(V72),notes:f.string().default("")}))});var JEw=f.object({}).strict();function sW0(A={}){return JEw.parse(A),[J1A()]}fA();C0();C0();var I1A=f.object({enabled:f.boolean().default(!0),pdsEndpoint:f.url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:f.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:f.string().optional().describe("DID of the PDS repo that owns records"),appPassword:f.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:f.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:f.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});C0();var FEw=f.looseObject({message:f.string()}),IEw=f.looseObject({did:f.string(),handle:f.string(),accessJwt:f.string(),refreshJwt:f.string()}),b1A=f.looseObject({uri:f.string(),cid:f.string()}),bEw=b1A.extend({value:f.record(f.string(),f.unknown())}),LEw=f.looseObject({$type:f.literal("blob").optional(),ref:f.looseObject({$link:f.string()}),mimeType:f.string(),size:f.number().int().nonnegative()}).transform((A)=>({...A.$type!==void 0?{$type:A.$type}:{},ref:{$link:A.ref.$link},mimeType:A.mimeType,size:A.size})),kEw=f.looseObject({blob:LEw});function _Ew(A){return A.replace(/\/+$/,"")}var NEw=(A,Q)=>fetch(A,Q);async function ga(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=FEw.safeParse($);throw Error(B.success?B.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse($)}class Ea{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=_Ew(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??NEw}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 ga(A,IEw);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 ga(w,b1A)}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 ga(w,b1A)}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 ga(w,bEw)}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 ga(w,kEw)}async getSession(){return this.session??=await this.createSession(),this.session}}function EM(A){return A?.startsWith("did:web:")??!1}function aW0(A){if(!EM(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 L72(A){if(!EM(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 k72(A){return A.replace(/\/+$/,"")}function Ta(A){return`did:web:${encodeURIComponent(A)}`}function tW0(A){return`${Ta(A)}:anchor`}function L1A(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function _72(A,Q){let w=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...L1A(Q),...w&&{alsoKnownAs:w},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:k72(A.pdsEndpoint)}]}}function N72(A){if(!EM(A.brainDid))return null;return _72(A,A.brainDid)}function b72(A,Q){if(!A||!Q)return;let w=aW0(A),$=L72(A);if(!w||!$)return;return{path:$,hostname:w,document:Q}}function eW0(A){let Q=[],w=b72(A.brainDid,N72(A));if(w)Q.push(w);if(EM(A.anchorDid)&&A.anchorDid!==A.brainDid){let $=b72(A.anchorDid,L1A(A.anchorDid));if($)Q.push($)}return Q}function k1A(A,Q){let w=[];if(!A.brainDid){let $=Ta(Q);w.push({path:"/.well-known/did.json",hostname:Q,document:_72(A,$)})}if(!A.anchorDid){let $=tW0(Q);w.push({path:"/anchor/did.json",hostname:Q,document:L1A($)})}return w}function jEw(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function PEw(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function j72(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function P72(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 MEw(A){let Q=A.metadata,w=j72(Q,"name"),$=j72(Q,"description");if(!w||!$)return;let B=P72(Q,"tags"),X=P72(Q,"examples");return{id:PEw(w),name:w,description:$,...B&&{tags:B},...X&&{examples:X}}}async function OEw(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map((w)=>MEw(w)).filter((w)=>w!==void 0).slice(0,100)}async function _1A(A,Q,w=new Date){let $=A.identity.get(),B=A.identity.getProfile(),X=await A.identity.getAppInfo(),Y=jEw(A.siteUrl??B.website,void 0);if(!Y)throw Error("AT Protocol brain card publishing requires siteUrl");let Z=new URL(Y).hostname,H=Q.brainDid??Ta(Z),W=Q.anchorDid??tW0(Z);if(EM(H)){if(aW0(H)!==Z)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let K=await OEw(A);return{$type:"ai.rizom.brain.card",siteUrl:Y,brain:{did:H,name:$.name,role:$.role,purpose:$.purpose,values:$.values},anchor:{did:W,name:B.name,kind:B.kind},skills:K,model:X.model,version:X.version,createdAt:w.toISOString(),updatedAt:w.toISOString()}}var M72={name:"@brains/atproto",version:"0.2.0-alpha.168",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 O72=m6["ai.rizom.brain.card"],REw=f.looseObject({did:f.string()}),vEw=f.looseObject({service:f.array(f.looseObject({id:f.string().optional(),type:f.string().optional(),serviceEndpoint:f.string().optional()})).optional()}),hEw="ai.rizom.brain.card",CEw="self",x72=50;class N1A extends Uw{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",M72,A,I1A);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??NB.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=eW0(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=[...eW0(this.config),...k1A(this.config,X)].filter((H)=>H.path===$),Z=Y.find((H)=>H.hostname===X)??Y[0];if(!Z)return new Response("Not found",{status:404});return new Response(JSON.stringify(Z.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let w=await _1A(A,this.config);jV(O72,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 H=await X.putRecord({repo:Z,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:w});return{record:w,repo:Z,uri:H.uri,cid:H.cid,dryRun:!1}}async publishEntity(A,Q){let w=this.projectionRegistry.get(Q.entityType);if(!w)throw Error(`No AT Protocol projection registered for ${Q.entityType}`);return this.publishProjectedEntity(A,Q,w)}async publishPost(A,Q){let w=this.projectionRegistry.get("post");if(!w)throw Error("No AT Protocol projection registered for post");return this.publishProjectedEntity(A,{entityType:"post",...Q},w)}async discoverBrainCards(A,Q){let w=[...new Set(Q.repos.map((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>x72)throw Error(`AT Protocol discovery accepts at most ${x72} 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 H=await Z.getRecord({repo:Y.repoDid,collection:hEw,rkey:CEw});jV(O72,H.value);let W=gEw(H.uri)??Y.repoDid,K=`${W}:${H.uri}:${H.cid}`;if($.has(K)){B.push({repo:X,status:"skipped",repoDid:W,uri:H.uri,cid:H.cid,error:"Duplicate brain card in discovery batch"});continue}$.add(K),await A.messaging.send({type:zr,payload:{repoDid:W,uri:H.uri,cid:H.cid,record:H.value},broadcast:!0}),B.push({repo:X,status:"discovered",repoDid:W,uri:H.uri,cid:H.cid})}catch(Y){B.push({repo:X,status:"skipped",error:dA(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:dA(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 G=await w.buildRecord({entity:$,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return jV(w.lexicon,G),{record:G,dryRun:!0,...X&&{repo:X}}}let Y=this.resolveAppPassword();if(!this.config.identifier||!Y)throw Error("AT Protocol publishing requires identifier and app password configuration");let Z=this.createPdsClient(Y),H=await Z.createSession(),W=X??H.did,K=await w.buildRecord({entity:$,context:A,config:this.config,client:Z,...Q.topics&&{topics:Q.topics}});if(jV(w.lexicon,K),!Z.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let U=await Z.putRecord({repo:W,collection:w.collection,rkey:yEw($.id),...w.validate!==void 0&&{validate:w.validate},record:K});return await w.onPublished?.({entity:$,context:A,record:K,uri:U.uri,cid:U.cid}),{record:K,repo:W,uri:U.uri,cid:U.cid,dryRun:!1}}async findPublishEntity(A,Q){if(Q.entityId)return A.entityService.getEntity({entityType:Q.entityType,id:Q.entityId});if(Q.slug)return(await A.entityService.listEntities({entityType:Q.entityType,options:{filter:{metadata:{slug:Q.slug}}}}))[0]??null;return null}createPublicPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""});return new Ea({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 $=REw.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(EEw(A)):void 0,w=vEw.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 Ea({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function yEw(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function gEw(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function EEw(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 AK0(A,Q){return new N1A(A,Q)}fA();C0();var QK0={name:"@brains/rover",version:"0.2.0-alpha.168",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 SEw=f.looseObject({});class R72 extends Uw{constructor(A={}){super("rover-profile",QK0,A,SEw)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",g_)}}function v72(A={}){return new R72(A)}fA();C0();n$();fA();fA();var Sa=U3.extend(g_.shape);class wK0{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([hR($,Sa),tZ0($,{entityType:"post",count:3,parse:Gs}),tZ0($,{entityType:"deck",count:3,parse:Is}),Ks($)]),H={profile:B,posts:X,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:ha0(Z.cta),sections:Z.sections??{}};return Q.parse(H)}}fA();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 hR(w.entityService,Sa)};return Q.parse(B)}}import{jsxDEV as t$,Fragment as cEw}from"preact/jsx-dev-runtime";var mEw="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",uEw="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",j1A=({number:A,title:Q,blurb:w,children:$})=>t$("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:t$("div",{className:"max-w-6xl mx-auto",children:t$("div",{className:mEw,children:[t$(Sr0,{title:Q,number:A,blurb:w},void 0,!1,void 0,this),t$("div",{className:uEw,"aria-hidden":"true"},void 0,!1,void 0,this),t$("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),P1A=({profile:A,posts:Q,decks:w,postsListUrl:$,decksListUrl:B,cta:X,sections:Y})=>{let Z=A.tagline?.length?A.tagline:A.description,H=Q.map((q)=>({id:q.id,url:q.url,title:q.metadata.title,date:q.metadata.publishedAt??q.created,description:q.frontmatter.excerpt,series:q.frontmatter.seriesName&&q.frontmatter.seriesIndex?{name:q.frontmatter.seriesName,index:q.frontmatter.seriesIndex}:void 0})),W=w.map((q)=>({id:q.id,url:q.url,title:q.frontmatter.title||q.id,date:q.frontmatter.publishedAt??q.created,description:q.frontmatter.description})),K=A.name||"Home",U=[A.intro,A.description,Z].find((q)=>q)??"Professional site",G=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return t$(cEw,{children:[t$(Bw,{title:K,description:U,ogType:"website"},void 0,!1,void 0,this),t$("div",{className:"homepage-list bg-theme",children:[t$("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:t$("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&t$("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[t$("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),t$("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z&&t$("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:KY0(Z,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&t$("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:KY0(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),t$(j1A,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:t$(WY0,{items:H,viewAllUrl:$,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),W.length>0&&t$(j1A,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:t$(WY0,{items:W,viewAllUrl:B,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),G&&t$(j1A,{number:"03",title:"About",blurb:Y.about?.blurb,children:t$("div",{className:"flex flex-col gap-8",children:[A.description&&t$("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&&t$(mr0,{subjects:A.expertise},void 0,!1,void 0,this),t$("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",t$("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),t$(_r0,{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 z$,Fragment as lEw}from"preact/jsx-dev-runtime";var M1A=({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 z$(lEw,{children:[z$(Bw,{title:Q,description:w,ogType:"profile"},void 0,!1,void 0,this),z$("div",{className:"about-page bg-theme",children:[z$("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:z$("div",{className:"relative z-10 max-w-4xl mx-auto",children:[z$("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&&z$("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),z$("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&z$("section",{className:"content-section-reveal mb-20 md:mb-28",children:z$(i9,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),$&&z$("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&z$("section",{children:[z$("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),z$("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map((B,X)=>z$("li",{className:Zo({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&&z$("section",{children:[z$("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),z$("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&&z$("section",{children:[z$("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),z$("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)&&z$("section",{children:[z$("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),z$("div",{className:"space-y-4",children:[A.email&&z$("p",{className:"text-lg",children:z$("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&&z$("p",{className:"text-lg",children:z$("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&&z$("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map((B,X)=>z$(p9,{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 FX,Fragment as h72}from"preact/jsx-dev-runtime";var O1A=()=>{return FX(h72,{children:[FX(Bw,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),FX("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:FX("div",{className:"text-center max-w-md",children:[FX("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),FX("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),FX("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),FX(p9,{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)},x1A=()=>{return FX(h72,{children:[FX(Bw,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),FX("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:FX("div",{className:"text-center max-w-md",children:[FX("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),FX("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),FX("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),FX(p9,{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)};C0();var C72=f.object({label:f.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:f.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),pEw={post:{label:"Post"},deck:{label:"Deck"}},y72=f.object({entityDisplay:f.object({post:C72,deck:C72}).default(pEw).describe("Display metadata for post and deck entity types used by the homepage")});var g72={name:"@brains/site-professional",version:"0.2.0-alpha.168",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 dEw=f.object({blurb:f.string().optional().describe("Short italic subtitle under the section title")}),nEw=f.object({heading:f.string(),buttonText:f.string(),buttonLink:f.string()}),E72=f.looseObject({name:f.string(),kind:f.enum(["professional","team","collective"]),organization:f.string().optional(),description:f.string().optional(),avatar:f.string().optional(),website:f.string().optional(),email:f.string().optional(),socialLinks:f.array(f.object({platform:f.enum(["github","instagram","linkedin","email","website"]),url:f.string(),label:f.string().optional()})).optional(),tagline:f.string().optional(),intro:f.string().optional(),story:f.string().optional(),role:f.string().optional(),audience:f.string().optional(),expertise:f.array(f.string()).optional(),currentFocus:f.string().optional(),availability:f.string().optional(),desiredTone:f.string().optional()}),rEw=f.looseObject({id:f.string(),entityType:f.literal("post"),content:f.string(),created:f.string(),updated:f.string(),contentHash:f.string(),metadata:f.looseObject({title:f.string(),publishedAt:f.string().optional()}),frontmatter:f.looseObject({excerpt:f.string(),seriesName:f.string().optional(),seriesIndex:f.number().optional()}),body:f.string(),url:f.string().optional(),typeLabel:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),seriesUrl:f.string().optional(),coverImageUrl:f.string().optional(),ogImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional(),coverImageSrcset:f.string().optional(),coverImageSizes:f.string().optional()}),oEw=f.looseObject({id:f.string(),entityType:f.literal("deck"),content:f.string(),created:f.string(),updated:f.string(),contentHash:f.string(),metadata:f.looseObject({title:f.string(),publishedAt:f.string().optional()}),frontmatter:f.looseObject({title:f.string(),description:f.string().optional(),publishedAt:f.string().optional()}),body:f.string(),url:f.string().optional(),typeLabel:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),coverImageUrl:f.string().optional(),ogImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()});class R1A extends Uw{dependencies=["blog","decks"];constructor(A){super("professional-site",g72,A,y72)}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 wK0($,B);A.entities.registerDataSource(X);let Y=new $K0;A.entities.registerDataSource(Y);let Z=f.object({profile:E72,posts:f.array(rEw),decks:f.array(oEw),postsListUrl:f.string(),decksListUrl:f.string(),cta:nEw,sections:f.record(f.string(),dEw)}),H=f.object({profile:E72}),W=f.object({});A.templates.register({"homepage-list":s1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:Z,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:P1A}}),about:s1({name:"about",description:"About page with full profile information",schema:H,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:M1A}}),"subscribe-thanks":s1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:W,requiredPermission:"public",layout:{component:O1A}}),"subscribe-error":s1({name:"subscribe-error",description:"Newsletter subscription error page",schema:W,requiredPermission:"public",layout:{component:x1A}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function T72(A){return new R1A(A??{})}var S72=[{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 m72({sections:A,siteInfo:Q,slots:w,wordmark:$}){return BK0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[BK0(Mr0,{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(Pr0,{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 sEw={layouts:{default:m72},routes:S72,plugin:T72,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"}}}},ma=sEw;var u72=`/*
|
|
10879
|
+
`).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 zEw=new Y6(GEw,{title:"Agent",mappings:[{key:"about",label:"About",type:"string"},{key:"skills",label:"Skills",type:"custom",formatter:DEw,parser:qEw},{key:"notes",label:"Notes",type:"string"}]});class F72 extends r2{constructor(){super({entityType:"agent",purpose:"An agent entity used for SWOT evaluation.",schema:KEw,frontmatterSchema:WEw})}fromMarkdown(A){return{content:A,entityType:"agent"}}createAgentContent(A){let Q=zEw.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 I72 extends r2{constructor(){super({entityType:"skill",purpose:"A skill entity used for SWOT evaluation.",schema:UEw,frontmatterSchema:F1A})}fromMarkdown(A){let Q=this.parseFrontMatter(A,F1A);return{content:A,entityType:"skill",metadata:Q}}createSkillContent(A){return this.buildMarkdown("",A)}}var Ml8=new F72,Ol8=new I72,VEw=f.object({name:f.string(),description:f.string(),tags:f.array(f.string()),examples:f.array(f.string())}),xl8=f.object({skills:f.array(VEw),agents:f.array(f.object({id:f.string().optional(),name:f.string(),kind:f.enum(["professional","team","collective"]),organization:f.string().optional(),brainName:f.string(),url:f.url(),did:f.string().optional(),status:f.enum(["discovered","approved"]),discoveredAt:f.string().datetime().optional(),about:f.string(),skills:f.array(V72),notes:f.string().default("")}))});var JEw=f.object({}).strict();function sW0(A={}){return JEw.parse(A),[J1A()]}fA();C0();C0();var I1A=f.object({enabled:f.boolean().default(!0),pdsEndpoint:f.url().default("https://bsky.social").describe("AT Protocol PDS service endpoint"),identifier:f.string().optional().describe("PDS login identifier, usually a handle or account DID"),repoDid:f.string().optional().describe("DID of the PDS repo that owns records"),appPassword:f.string().optional().describe("App password for prototype authentication; supply via ${ENV_VAR} interpolation, never a committed literal"),anchorDid:f.string().optional().describe("Optional human/operator DID referenced from records; defaults to did:web:<site-host>:anchor when omitted"),brainDid:f.string().optional().describe("Optional public brain DID referenced from records; defaults to did:web:<site-host> when omitted")});C0();var FEw=f.looseObject({message:f.string()}),IEw=f.looseObject({did:f.string(),handle:f.string(),accessJwt:f.string(),refreshJwt:f.string()}),b1A=f.looseObject({uri:f.string(),cid:f.string()}),bEw=b1A.extend({value:f.record(f.string(),f.unknown())}),LEw=f.looseObject({$type:f.literal("blob").optional(),ref:f.looseObject({$link:f.string()}),mimeType:f.string(),size:f.number().int().nonnegative()}).transform((A)=>({...A.$type!==void 0?{$type:A.$type}:{},ref:{$link:A.ref.$link},mimeType:A.mimeType,size:A.size})),kEw=f.looseObject({blob:LEw});function _Ew(A){return A.replace(/\/+$/,"")}var NEw=(A,Q)=>fetch(A,Q);async function ga(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=FEw.safeParse($);throw Error(B.success?B.data.message:`AT Protocol request failed with ${A.status}`)}return Q.parse($)}class Ea{pdsEndpoint;identifier;appPassword;fetchFn;session;constructor(A){this.pdsEndpoint=_Ew(A.pdsEndpoint),this.identifier=A.identifier,this.appPassword=A.appPassword,this.fetchFn=A.fetch??NEw}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 ga(A,IEw);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 ga(w,b1A)}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 ga(w,b1A)}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 ga(w,bEw)}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 ga(w,kEw)}async getSession(){return this.session??=await this.createSession(),this.session}}function EM(A){return A?.startsWith("did:web:")??!1}function aW0(A){if(!EM(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 L72(A){if(!EM(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 k72(A){return A.replace(/\/+$/,"")}function Ta(A){return`did:web:${encodeURIComponent(A)}`}function tW0(A){return`${Ta(A)}:anchor`}function L1A(A){return{"@context":["https://www.w3.org/ns/did/v1"],id:A}}function _72(A,Q){let w=A.identifier?.startsWith("did:")?void 0:A.identifier?[`at://${A.identifier}`]:void 0;return{...L1A(Q),...w&&{alsoKnownAs:w},service:[{id:"#atproto_pds",type:"AtprotoPersonalDataServer",serviceEndpoint:k72(A.pdsEndpoint)}]}}function N72(A){if(!EM(A.brainDid))return null;return _72(A,A.brainDid)}function b72(A,Q){if(!A||!Q)return;let w=aW0(A),$=L72(A);if(!w||!$)return;return{path:$,hostname:w,document:Q}}function eW0(A){let Q=[],w=b72(A.brainDid,N72(A));if(w)Q.push(w);if(EM(A.anchorDid)&&A.anchorDid!==A.brainDid){let $=b72(A.anchorDid,L1A(A.anchorDid));if($)Q.push($)}return Q}function k1A(A,Q){let w=[];if(!A.brainDid){let $=Ta(Q);w.push({path:"/.well-known/did.json",hostname:Q,document:_72(A,$)})}if(!A.anchorDid){let $=tW0(Q);w.push({path:"/anchor/did.json",hostname:Q,document:L1A($)})}return w}function jEw(A,Q){if(!A)return;try{return new URL(A,Q).toString()}catch{return}}function PEw(A){let Q=A.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,200);return Q.length>0?Q:"skill"}function j72(A,Q){let w=A[Q];return typeof w==="string"&&w.length>0?w:void 0}function P72(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 MEw(A){let Q=A.metadata,w=j72(Q,"name"),$=j72(Q,"description");if(!w||!$)return;let B=P72(Q,"tags"),X=P72(Q,"examples");return{id:PEw(w),name:w,description:$,...B&&{tags:B},...X&&{examples:X}}}async function OEw(A){if(!A.entityService.hasEntityType("skill"))return[];return(await A.entityService.listEntities({entityType:"skill",options:{filter:{visibilityScope:"public"}}})).map((w)=>MEw(w)).filter((w)=>w!==void 0).slice(0,100)}async function _1A(A,Q,w=new Date){let $=A.identity.get(),B=A.identity.getProfile(),X=await A.identity.getAppInfo(),Y=jEw(A.siteUrl??B.website,void 0);if(!Y)throw Error("AT Protocol brain card publishing requires siteUrl");let Z=new URL(Y).hostname,H=Q.brainDid??Ta(Z),W=Q.anchorDid??tW0(Z);if(EM(H)){if(aW0(H)!==Z)throw Error("AT Protocol brain card did:web host must match siteUrl host")}let K=await OEw(A);return{$type:"ai.rizom.brain.card",siteUrl:Y,brain:{did:H,name:$.name,role:$.role,purpose:$.purpose,values:$.values},anchor:{did:W,name:B.name,kind:B.kind},skills:K,model:X.model,version:X.version,createdAt:w.toISOString(),updatedAt:w.toISOString()}}var M72={name:"@brains/atproto",version:"0.2.0-alpha.169",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 O72=m6["ai.rizom.brain.card"],REw=f.looseObject({did:f.string()}),vEw=f.looseObject({service:f.array(f.looseObject({id:f.string().optional(),type:f.string().optional(),serviceEndpoint:f.string().optional()})).optional()}),hEw="ai.rizom.brain.card",CEw="self",x72=50;class N1A extends Uw{deps;projectionRegistry;constructor(A={},Q={}){super("atproto",M72,A,I1A);this.deps=Q,this.projectionRegistry=Q.projectionRegistry??NB.getInstance()}getWebRoutes(){if(!this.config.enabled)return[];let A=eW0(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=[...eW0(this.config),...k1A(this.config,X)].filter((H)=>H.path===$),Z=Y.find((H)=>H.hostname===X)??Y[0];if(!Z)return new Response("Not found",{status:404});return new Response(JSON.stringify(Z.document),{headers:{"Content-Type":"application/did+json"}})}}))}async publishBrainCard(A,Q={}){let w=await _1A(A,this.config);jV(O72,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 H=await X.putRecord({repo:Z,collection:"ai.rizom.brain.card",rkey:"self",validate:!1,record:w});return{record:w,repo:Z,uri:H.uri,cid:H.cid,dryRun:!1}}async publishEntity(A,Q){let w=this.projectionRegistry.get(Q.entityType);if(!w)throw Error(`No AT Protocol projection registered for ${Q.entityType}`);return this.publishProjectedEntity(A,Q,w)}async publishPost(A,Q){let w=this.projectionRegistry.get("post");if(!w)throw Error("No AT Protocol projection registered for post");return this.publishProjectedEntity(A,{entityType:"post",...Q},w)}async discoverBrainCards(A,Q){let w=[...new Set(Q.repos.map((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>x72)throw Error(`AT Protocol discovery accepts at most ${x72} 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 H=await Z.getRecord({repo:Y.repoDid,collection:hEw,rkey:CEw});jV(O72,H.value);let W=gEw(H.uri)??Y.repoDid,K=`${W}:${H.uri}:${H.cid}`;if($.has(K)){B.push({repo:X,status:"skipped",repoDid:W,uri:H.uri,cid:H.cid,error:"Duplicate brain card in discovery batch"});continue}$.add(K),await A.messaging.send({type:zr,payload:{repoDid:W,uri:H.uri,cid:H.cid,record:H.value},broadcast:!0}),B.push({repo:X,status:"discovered",repoDid:W,uri:H.uri,cid:H.cid})}catch(Y){B.push({repo:X,status:"skipped",error:dA(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:dA(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 G=await w.buildRecord({entity:$,context:A,config:this.config,...Q.topics&&{topics:Q.topics},dryRun:!0});return jV(w.lexicon,G),{record:G,dryRun:!0,...X&&{repo:X}}}let Y=this.resolveAppPassword();if(!this.config.identifier||!Y)throw Error("AT Protocol publishing requires identifier and app password configuration");let Z=this.createPdsClient(Y),H=await Z.createSession(),W=X??H.did,K=await w.buildRecord({entity:$,context:A,config:this.config,client:Z,...Q.topics&&{topics:Q.topics}});if(jV(w.lexicon,K),!Z.putRecord)throw Error("AT Protocol PDS client does not support record upserts");let U=await Z.putRecord({repo:W,collection:w.collection,rkey:yEw($.id),...w.validate!==void 0&&{validate:w.validate},record:K});return await w.onPublished?.({entity:$,context:A,record:K,uri:U.uri,cid:U.cid}),{record:K,repo:W,uri:U.uri,cid:U.cid,dryRun:!1}}async findPublishEntity(A,Q){if(Q.entityId)return A.entityService.getEntity({entityType:Q.entityType,id:Q.entityId});if(Q.slug)return(await A.entityService.listEntities({entityType:Q.entityType,options:{filter:{metadata:{slug:Q.slug}}}}))[0]??null;return null}createPublicPdsClient(A){if(this.deps.createPdsClient)return this.deps.createPdsClient({pdsEndpoint:A,identifier:this.config.identifier??"",appPassword:this.config.appPassword??""});return new Ea({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 $=REw.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(EEw(A)):void 0,w=vEw.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 Ea({pdsEndpoint:this.config.pdsEndpoint,identifier:this.config.identifier??"",appPassword:A})}resolveAppPassword(){return this.config.appPassword}}function yEw(A){let Q=A.replace(/[^A-Za-z0-9._~:-]/g,"_").slice(0,512);return Q.length>0?Q:"self"}function gEw(A){return/^at:\/\/([^/]+)/.exec(A)?.[1]}function EEw(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 AK0(A,Q){return new N1A(A,Q)}fA();C0();var QK0={name:"@brains/rover",version:"0.2.0-alpha.169",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 SEw=f.looseObject({});class R72 extends Uw{constructor(A={}){super("rover-profile",QK0,A,SEw)}async onRegister(A){A.entities.extendFrontmatterSchema("anchor-profile",g_)}}function v72(A={}){return new R72(A)}fA();C0();n$();fA();fA();var Sa=U3.extend(g_.shape);class wK0{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([hR($,Sa),tZ0($,{entityType:"post",count:3,parse:Gs}),tZ0($,{entityType:"deck",count:3,parse:Is}),Ks($)]),H={profile:B,posts:X,decks:Y,postsListUrl:this.postsListUrl,decksListUrl:this.decksListUrl,cta:ha0(Z.cta),sections:Z.sections??{}};return Q.parse(H)}}fA();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 hR(w.entityService,Sa)};return Q.parse(B)}}import{jsxDEV as t$,Fragment as cEw}from"preact/jsx-dev-runtime";var mEw="grid md:grid-cols-[14rem_1px_1fr] gap-y-2 gap-x-0 md:gap-16 items-start",uEw="border-t md:border-t-0 md:border-l border-rule-strong md:self-stretch",j1A=({number:A,title:Q,blurb:w,children:$})=>t$("section",{className:"py-20 border-b border-rule px-6 md:px-12",children:t$("div",{className:"max-w-6xl mx-auto",children:t$("div",{className:mEw,children:[t$(Sr0,{title:Q,number:A,blurb:w},void 0,!1,void 0,this),t$("div",{className:uEw,"aria-hidden":"true"},void 0,!1,void 0,this),t$("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),P1A=({profile:A,posts:Q,decks:w,postsListUrl:$,decksListUrl:B,cta:X,sections:Y})=>{let Z=A.tagline?.length?A.tagline:A.description,H=Q.map((q)=>({id:q.id,url:q.url,title:q.metadata.title,date:q.metadata.publishedAt??q.created,description:q.frontmatter.excerpt,series:q.frontmatter.seriesName&&q.frontmatter.seriesIndex?{name:q.frontmatter.seriesName,index:q.frontmatter.seriesIndex}:void 0})),W=w.map((q)=>({id:q.id,url:q.url,title:q.frontmatter.title||q.id,date:q.frontmatter.publishedAt??q.created,description:q.frontmatter.description})),K=A.name||"Home",U=[A.intro,A.description,Z].find((q)=>q)??"Professional site",G=Boolean(A.description)||A.expertise!==void 0&&A.expertise.length>0;return t$(cEw,{children:[t$(Bw,{title:K,description:U,ogType:"website"},void 0,!1,void 0,this),t$("div",{className:"homepage-list bg-theme",children:[t$("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:t$("div",{className:"relative z-10 max-w-6xl mx-auto w-full",children:[A.name&&t$("div",{className:"flex items-center gap-[0.6rem] mb-6 font-mono text-[0.7rem] font-medium uppercase tracking-[0.22em] text-accent",children:[t$("span",{className:"w-[18px] h-px bg-accent","aria-hidden":"true"},void 0,!1,void 0,this),t$("span",{children:A.name},void 0,!1,void 0,this)]},void 0,!0,void 0,this),Z&&t$("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:KY0(Z,"italic font-normal text-accent [font-variation-settings:'opsz'_144,'SOFT'_80]")},void 0,!1,void 0,this),A.intro&&t$("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:KY0(A.intro,"italic text-accent")},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),t$(j1A,{number:"01",title:"Essays",blurb:Y.essays?.blurb,children:t$(WY0,{items:H,viewAllUrl:$,viewAllLabel:"View all essays"},void 0,!1,void 0,this)},void 0,!1,void 0,this),W.length>0&&t$(j1A,{number:"02",title:"Presentations",blurb:Y.presentations?.blurb,children:t$(WY0,{items:W,viewAllUrl:B,viewAllLabel:"View all presentations"},void 0,!1,void 0,this)},void 0,!1,void 0,this),G&&t$(j1A,{number:"03",title:"About",blurb:Y.about?.blurb,children:t$("div",{className:"flex flex-col gap-8",children:[A.description&&t$("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&&t$(mr0,{subjects:A.expertise},void 0,!1,void 0,this),t$("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",t$("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),t$(_r0,{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 z$,Fragment as lEw}from"preact/jsx-dev-runtime";var M1A=({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 z$(lEw,{children:[z$(Bw,{title:Q,description:w,ogType:"profile"},void 0,!1,void 0,this),z$("div",{className:"about-page bg-theme",children:[z$("header",{className:"hero-bg-pattern relative w-full py-16 md:py-24 px-6 md:px-12 bg-theme overflow-hidden",children:z$("div",{className:"relative z-10 max-w-4xl mx-auto",children:[z$("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&&z$("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),z$("div",{className:"container mx-auto px-6 md:px-12 max-w-4xl py-12 md:py-16",children:[A.story&&z$("section",{className:"content-section-reveal mb-20 md:mb-28",children:z$(i9,{markdown:A.story},void 0,!1,void 0,this)},void 0,!1,void 0,this),$&&z$("div",{className:"content-section-reveal grid md:grid-cols-2 gap-x-16 gap-y-12",children:[A.expertise&&A.expertise.length>0&&z$("section",{children:[z$("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Expertise"},void 0,!1,void 0,this),z$("ul",{className:"flex flex-wrap gap-3",children:A.expertise.map((B,X)=>z$("li",{className:Zo({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&&z$("section",{children:[z$("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Current Focus"},void 0,!1,void 0,this),z$("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&&z$("section",{children:[z$("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Availability"},void 0,!1,void 0,this),z$("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)&&z$("section",{children:[z$("h2",{className:"text-sm tracking-widest uppercase text-theme-muted mb-6",children:"Contact"},void 0,!1,void 0,this),z$("div",{className:"space-y-4",children:[A.email&&z$("p",{className:"text-lg",children:z$("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&&z$("p",{className:"text-lg",children:z$("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&&z$("div",{className:"flex flex-wrap gap-4 mt-4",children:A.socialLinks.map((B,X)=>z$(p9,{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 FX,Fragment as h72}from"preact/jsx-dev-runtime";var O1A=()=>{return FX(h72,{children:[FX(Bw,{title:"Thanks for subscribing!",description:"You've successfully subscribed to the newsletter."},void 0,!1,void 0,this),FX("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:FX("div",{className:"text-center max-w-md",children:[FX("div",{className:"text-6xl mb-6",children:"\uD83C\uDF89"},void 0,!1,void 0,this),FX("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Thanks for subscribing!"},void 0,!1,void 0,this),FX("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),FX(p9,{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)},x1A=()=>{return FX(h72,{children:[FX(Bw,{title:"Subscription failed",description:"There was a problem with your subscription."},void 0,!1,void 0,this),FX("div",{className:"min-h-[60vh] flex items-center justify-center px-6",children:FX("div",{className:"text-center max-w-md",children:[FX("div",{className:"text-6xl mb-6",children:"\uD83D\uDE22"},void 0,!1,void 0,this),FX("h1",{className:"text-3xl font-semibold mb-4 text-heading",children:"Something went wrong"},void 0,!1,void 0,this),FX("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),FX(p9,{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)};C0();var C72=f.object({label:f.string().describe("Display label for entity type (e.g., 'Essay')"),pluralName:f.string().optional().describe("URL path segment (defaults to label.toLowerCase() + 's')")}),pEw={post:{label:"Post"},deck:{label:"Deck"}},y72=f.object({entityDisplay:f.object({post:C72,deck:C72}).default(pEw).describe("Display metadata for post and deck entity types used by the homepage")});var g72={name:"@brains/site-professional",version:"0.2.0-alpha.169",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 dEw=f.object({blurb:f.string().optional().describe("Short italic subtitle under the section title")}),nEw=f.object({heading:f.string(),buttonText:f.string(),buttonLink:f.string()}),E72=f.looseObject({name:f.string(),kind:f.enum(["professional","team","collective"]),organization:f.string().optional(),description:f.string().optional(),avatar:f.string().optional(),website:f.string().optional(),email:f.string().optional(),socialLinks:f.array(f.object({platform:f.enum(["github","instagram","linkedin","email","website"]),url:f.string(),label:f.string().optional()})).optional(),tagline:f.string().optional(),intro:f.string().optional(),story:f.string().optional(),role:f.string().optional(),audience:f.string().optional(),expertise:f.array(f.string()).optional(),currentFocus:f.string().optional(),availability:f.string().optional(),desiredTone:f.string().optional()}),rEw=f.looseObject({id:f.string(),entityType:f.literal("post"),content:f.string(),created:f.string(),updated:f.string(),contentHash:f.string(),metadata:f.looseObject({title:f.string(),publishedAt:f.string().optional()}),frontmatter:f.looseObject({excerpt:f.string(),seriesName:f.string().optional(),seriesIndex:f.number().optional()}),body:f.string(),url:f.string().optional(),typeLabel:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),seriesUrl:f.string().optional(),coverImageUrl:f.string().optional(),ogImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional(),coverImageSrcset:f.string().optional(),coverImageSizes:f.string().optional()}),oEw=f.looseObject({id:f.string(),entityType:f.literal("deck"),content:f.string(),created:f.string(),updated:f.string(),contentHash:f.string(),metadata:f.looseObject({title:f.string(),publishedAt:f.string().optional()}),frontmatter:f.looseObject({title:f.string(),description:f.string().optional(),publishedAt:f.string().optional()}),body:f.string(),url:f.string().optional(),typeLabel:f.string().optional(),listUrl:f.string().optional(),listLabel:f.string().optional(),coverImageUrl:f.string().optional(),ogImageUrl:f.string().optional(),coverImageWidth:f.number().optional(),coverImageHeight:f.number().optional()});class R1A extends Uw{dependencies=["blog","decks"];constructor(A){super("professional-site",g72,A,y72)}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 wK0($,B);A.entities.registerDataSource(X);let Y=new $K0;A.entities.registerDataSource(Y);let Z=f.object({profile:E72,posts:f.array(rEw),decks:f.array(oEw),postsListUrl:f.string(),decksListUrl:f.string(),cta:nEw,sections:f.record(f.string(),dEw)}),H=f.object({profile:E72}),W=f.object({});A.templates.register({"homepage-list":s1({name:"homepage-list",description:"Professional homepage with essays and presentations",schema:Z,dataSourceId:"professional:homepage-list",requiredPermission:"public",layout:{component:P1A}}),about:s1({name:"about",description:"About page with full profile information",schema:H,dataSourceId:"professional:about",requiredPermission:"public",layout:{component:M1A}}),"subscribe-thanks":s1({name:"subscribe-thanks",description:"Newsletter subscription success page",schema:W,requiredPermission:"public",layout:{component:O1A}}),"subscribe-error":s1({name:"subscribe-error",description:"Newsletter subscription error page",schema:W,requiredPermission:"public",layout:{component:x1A}})}),this.logger.info("Professional site plugin registered successfully")}async getTools(){return[]}async getResources(){return[]}}function T72(A){return new R1A(A??{})}var S72=[{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 m72({sections:A,siteInfo:Q,slots:w,wordmark:$}){return BK0("div",{className:"flex flex-col min-h-screen bg-theme overflow-x-clip",children:[BK0(Mr0,{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(Pr0,{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 sEw={layouts:{default:m72},routes:S72,plugin:T72,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"}}}},ma=sEw;var u72=`/*
|
|
10880
10880
|
* Default theme \u2014 simplified editorial base inspired by the Rizom family.
|
|
10881
10881
|
*
|
|
10882
10882
|
* This theme is intentionally less branded than @brains/theme-rizom. It
|
|
@@ -13891,7 +13891,7 @@ facts, owners, or tasks. Return only the required structured JSON.`});C0();var N
|
|
|
13891
13891
|
`);return this.truncateContent($||Q||RT(A))}truncateContent(A){if(A.length<=pU2)return A;let Q=A.slice(0,pU2-1),w=Q.search(/\s\S*$/);return`${(w>0?Q.slice(0,w):Q).trimEnd()}\u2026`}isSummaryEntity(A){return A.entityType===aB}isDecisionEntity(A){return A.entityType===RH}getEntitySpaceId(A){let Q=A.metadata;if("spaceId"in Q&&typeof Q.spaceId==="string")return Q.spaceId;return FG(Q)}}var enw=5,Arw=3;function pwA(A){A.messaging.subscribe(ek,async(Q)=>{let w=vm.parse(Q.payload);return{success:!0,data:await _U0(A,w)}})}async function _U0(A,Q){let w=P8(Q.userPermissionLevel);if(!Q.channelId)return iU2(A,Q,{visibilityScope:w,reason:"no-channel-context",items:[]}),{items:[]};let $=new vT(A),B=await $.retrieve({query:Q.message,conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:enw,visibilityScope:w}),X=B.results.length===0?await $.retrieve({conversationId:Q.conversationId,interfaceType:Q.interfaceType,channelId:Q.channelId,limit:Arw,visibilityScope:w}):void 0,Y=B.results.length>0,Z=Y?B.results:X?.results??[];return iU2(A,Q,{visibilityScope:w,spaceId:B.spaceId??X?.spaceId,reason:Z.length>0?"memory-injected":"no-same-space-memory",items:Z.map((H)=>Qrw(H,Y))}),{items:Z.map(wrw)}}function iU2(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 Qrw(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 wrw(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}}}C0();Kf();var rU2=f.union([f.enum(["public","shared","restricted"]),f.literal("private")]).optional().transform((A)=>{if(A===void 0)return"public";if(A==="private")return"restricted";return A}),oU2=f.enum(["user","assistant"]),$rw=f.object({actorId:f.string(),canonicalId:f.string().optional(),interfaceType:f.string(),role:oU2,displayName:f.string().optional(),username:f.string().optional(),isBot:f.boolean().optional()}),Brw=f.object({messageId:f.string().optional(),channelId:f.string().optional(),channelName:f.string().optional(),threadId:f.string().optional(),metadata:f.record(f.string(),f.unknown()).optional()}),dwA=f.object({role:oU2,content:f.string(),timestamp:f.string().datetime().optional(),actor:$rw.optional(),source:Brw.optional()}),Xrw=f.object({conversationId:f.string().default("eval-conversation"),messages:f.array(dwA)}),Yrw=f.object({conversationId:f.string()}),Zrw=f.object({conversationId:f.string().default("eval-conversation"),interfaceType:f.string().default("eval"),channelId:f.string().default("eval-channel"),channelName:f.string().optional(),projectionDecision:f.enum(["update","append"]).default("update"),existingSummary:f.string().optional(),existingMessageCount:f.number().int().min(0).default(0),messages:f.array(dwA)}),NU0=f.object({actorId:f.string(),canonicalId:f.string().optional(),displayName:f.string().optional()}),frw=NU0.extend({roles:f.array(f.enum(["user","assistant","system"])).default(["user"]),sourceActorIds:f.array(f.string()).optional()}),Hrw=f.object({actorId:f.string().optional(),canonicalId:f.string().optional(),displayName:f.string()}),sU2=f.object({id:f.string(),entityType:f.enum(["summary","decision","action-item"]),content:f.string(),excerpt:f.string().optional(),score:f.number().optional(),conversationId:f.string(),interfaceType:f.string(),channelId:f.string(),channelName:f.string().optional(),updated:f.string().datetime().optional(),visibility:rU2,status:f.string().optional(),participants:f.array(frw).optional(),decidedBy:f.array(NU0).optional(),mentionedBy:f.array(NU0).optional(),assignedTo:f.array(Hrw).optional(),requestedBy:f.array(NU0).optional()}),Wrw=f.object({query:f.string().optional(),conversationId:f.string().optional(),interfaceType:f.string().optional(),channelId:f.string().optional(),limit:f.number().int().min(1).optional(),includeOtherSpaces:f.boolean().optional(),actorId:f.string().optional(),canonicalId:f.string().optional(),visibilityScope:rU2.optional(),memory:f.array(sU2).optional()}),Krw=f.object({conversationId:f.string().default("eval-conversation"),message:f.string(),interfaceType:f.string().default("eval"),channelId:f.string().optional(),channelName:f.string().optional(),userPermissionLevel:f.enum(["anchor","trusted","public"]).default("trusted"),memory:f.array(sU2).optional()}),Urw=f.object({conversationId:f.string().default("eval-conversation"),existingSummary:f.string().optional(),existingMessageCount:f.number().int().min(0).default(0),messages:f.array(dwA)});function aU2(A){let{context:Q,logger:w,config:$}=A;Q.eval.registerHandler("summarizeMessages",async(B)=>{let X=Xrw.parse(B),Y=iwA(X.messages,X.conversationId),H=await new MT(Q,w,$).extract(Y);return H.entries.map((W)=>{let K=H.decisions.filter((G)=>G.timeRange.start>=W.timeRange.start).filter((G)=>G.timeRange.end<=W.timeRange.end).map((G)=>G.text),U=H.actionItems.filter((G)=>G.timeRange.start>=W.timeRange.start).filter((G)=>G.timeRange.end<=W.timeRange.end).map((G)=>G.text);return{...W,decisions:K,actionItems:U,keyPointsText:W.keyPoints.join(`
|
|
13892
13892
|
`),decisionsText:K.join(`
|
|
13893
13893
|
`),actionItemsText:U.join(`
|
|
13894
|
-
`)}})}),Q.eval.registerHandler("decideProjection",async(B)=>{let X=Urw.parse(B),Y=iwA(X.messages,X.conversationId),Z=X.existingSummary?dU2({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:$.projectionVersion,visibility:$.memoryVisibility}):null;return new oL(Q,w,$).decideProjection(Y,Z)}),Q.eval.registerHandler("retrieveMemory",async(B)=>{let X=Wrw.parse(B),Y=X.memory?nU2(Q,X.memory):Q;return new vT(Y).retrieve(X)}),Q.eval.registerHandler("buildAgentContext",async(B)=>{let X=Krw.parse(B),Y=X.memory?nU2(Q,X.memory):Q;return _U0(Y,X)}),Q.eval.registerHandler("projectMessages",async(B)=>{let X=Zrw.parse(B),Y=iwA(X.messages,X.conversationId),Z=Grw({conversationId:X.conversationId,interfaceType:X.interfaceType,channelId:X.channelId,channelName:X.channelName,messages:Y}),H=X.existingSummary?dU2({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:$.projectionVersion,visibility:$.memoryVisibility}):null,W=[],K=[],U=Drw({context:Q,conversation:Z,messages:Y,existing:H,upserted:W,deleted:K,projectionDecision:X.projectionDecision});return{result:await new oL(U,w,$).projectConversation(X.conversationId),summaries:W.filter((V)=>V.entityType==="summary"),decisions:W.filter((V)=>V.entityType==="decision"),actionItems:W.filter((V)=>V.entityType==="action-item"),deleted:K}}),Q.eval.registerHandler("projectConversation",async(B)=>{let X=Yrw.parse(B);return new oL(Q,w,$).projectConversation(X.conversationId)})}function dU2(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 iwA(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 Grw(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 Drw(A){let Q=FG(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 nU2(A,Q){let w=Q.map(qrw),$=w.map((B,X)=>({entity:B,score:Q[X]?.score??1,excerpt:Q[X]?.excerpt??RT(B)}));return{...A,entityService:{...A.entityService,search:async()=>$,listEntities:async({entityType:B})=>w.filter((X)=>X.entityType===B)}}}function qrw(A){if(A.entityType==="summary")return zrw(A);if(A.entityType==="decision")return Vrw(A);return Jrw(A)}function nwA(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:b6(A.content),visibility:A.visibility,created:Q,updated:Q}}function zrw(A){return{...nwA(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 Vrw(A){return{...nwA(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:FG(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 Jrw(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...nwA(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:FG(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 tU2={name:"@brains/conversation-memory",version:"0.2.0-alpha.168",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 Irw=new zK,brw=new NT,Lrw=new jT,krw=f.object({conversationId:f.string()});class rwA extends fw{entityType=aB;schema=Mt;adapter=Irw;constructor(A={}){super(GU0,tU2,A,mwA)}getConfig(){return this.config}getTemplates(){return{"summary-list":LU2,"summary-detail":kU2,"ai-response":_U2}}getDataSources(){return[new lwA(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:aB,job:{type:UU2,handler:new FU0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await M_(A,aB,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:gwA,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:GU0}}},sourceChange:{sourceKind:Uu,sourceTypes:[Uu],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[QR],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:gwA,deduplication:"skip",deduplicationKey:`conversation-memory:${w}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${w}`,pluginId:GU0}}}}}]}parseConversationMessagePayload(A){return krw.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:w}=this.parseConversationMessagePayload(Q),$=await A.conversations.get(w);if(!$)return!1;return nM({conversation:$,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(RH,Ot,brw),A.entities.register(qK,xt,Lrw),PU2({context:A,pluginId:this.id}),OU2({context:A,pluginId:this.id}),SU2({context:A,pluginId:this.id}),cU2({context:A,pluginId:this.id,config:this.config}),pwA(A),aU2({context:A,logger:this.logger,config:this.config})}}function owA(A={}){return new rwA(A)}fA();C0();C0();H5();var eU2=f.object({label:f.string(),href:f.string()}),AG2=f.object({label:f.string(),title:f.string(),detail:f.string()}),_rw=f.object({eyebrow:f.string(),name:f.string(),sub:f.string()}),Nrw=f.object({tone:f.enum(["capture","synthesis","share"]),title:f.string(),text:f.string()}),swA=f.object({captures:f.number(),links:f.number(),topics:f.number(),summaries:f.number(),peers:f.number()}),hT=f.object({eyebrow:f.string(),headline:f.string(),intro:f.string(),primaryCta:eU2,secondaryCta:eU2,inputs:f.array(AG2).min(1),outputs:f.array(AG2).min(1),core:_rw,legend:f.array(Nrw).min(1)}),awA=hT.extend({counts:swA}),QG2={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."}]},wG2=new Y6(hT,{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 jU0(A){return wG2.parse(A)}function $G2(A){return wG2.format(A)}C0();var jrw=f.looseObject({query:f.object({routeId:f.string().default("home"),sectionId:f.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),Prw={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class twA{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 $=jrw.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 QG2;return hT.parse(jU0($.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(Prw).map(async([w,$])=>[w,await this.countOrZero(A,$)]));return swA.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 BG2=f.object({label:f.string(),href:f.string()}),Mrw=f.object({label:f.string(),value:f.string(),note:f.string()}),Orw=f.object({eyebrow:f.string(),headline:f.string(),intro:f.string(),primaryCta:BG2,secondaryCta:BG2,signals:f.array(Mrw)}),xrw=f.object({phase:f.string(),title:f.string(),text:f.string()}),Rrw=f.object({eyebrow:f.string(),title:f.string(),intro:f.string(),steps:f.array(xrw)}),vrw=f.object({label:f.string(),title:f.string(),text:f.string()}),hrw=f.object({title:f.string(),intro:f.string(),cards:f.array(vrw)}),Crw=f.object({title:f.string(),intro:f.string(),points:f.array(f.string())}),yrw={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."]},grw="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function XG2({href:A,label:Q}){return b1("a",{href:A,className:grw,children:Q},void 0,!1,void 0,this)}function Erw({siteInfo:A,children:Q}){let w=[...A.navigation.primary,...A.navigation.secondary],$=A.cta??{buttonText:"Start here",buttonLink:"/about"};return b1(N2A,{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(XG2,{...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(XG2,{...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 Trw=({sections:A,siteInfo:Q})=>b1(Erw,{siteInfo:Q,children:A},void 0,!1,void 0,this);function Srw({eyebrow:A,headline:Q,intro:w,primaryCta:$,secondaryCta:B,signals:X}){return b1(IT,{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(ta,{href:$.href,size:"lg",variant:"primary-strong",children:$.label},void 0,!1,void 0,this),b1(ta,{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 mrw({eyebrow:A,title:Q,intro:w,steps:$}){return b1(IT,{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 urw({title:A,intro:Q,cards:w}){return b1(IT,{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 crw({title:A,intro:Q,points:w}){return b1(IT,{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 lrw=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},prw=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),ht=(A,Q,w=`${Q}s`)=>`${prw(A)} ${A===1?Q:w}`;function irw({eyebrow:A,headline:Q,intro:w,primaryCta:$,secondaryCta:B,inputs:X,outputs:Y,core:Z,legend:H,counts:W}){let K=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:ht(W.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:ht(W.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:ht(W.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:ht(W.summaries,"summary","summaries")}];return b1(IT,{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(ta,{href:$.href,size:"lg",variant:"primary-strong",children:$.label},void 0,!1,void 0,this),b1(ta,{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((U)=>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:U.label},void 0,!1,void 0,this),b1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),b1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this),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),K.map((U)=>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 ${U.className}`,children:U.label},U.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:[ht(W.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((U)=>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:U.label},void 0,!1,void 0,this),b1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),b1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:H.map((U)=>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 ${lrw(U.tone)}`},void 0,!1,void 0,this),U.title]},void 0,!0,void 0,this),b1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:U.text},void 0,!1,void 0,this)]},U.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var drw=s1({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:awA,formatter:{parse:(A)=>awA.parse({...jU0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>$G2(hT.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:irw}}),nrw=(A)=>Srw(Orw.parse(A)),rrw=(A)=>mrw(Rrw.parse(A)),orw=(A)=>urw(hrw.parse(A)),srw=(A)=>crw(Crw.parse(A)),YG2={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},ZG2={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:nrw,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...YG2,label:"Primary CTA"},secondaryCta:{...YG2,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:rrw,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:orw,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:srw,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},arw=[{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:yrw}]}],fG2=HU2({packageName:"@brains/relay/site",themeProfile:"studio",layout:Trw,routes:arw,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":drw},dataSources:[new twA]}});var HG2={name:"@brains/relay",version:"0.2.0-alpha.168",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 WG2=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],KG2=[...WG2,"image","site-info","site-content","site-builder"],Aow=[...KG2,"docs","decks"],Qow=["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."],wow=UI({name:"relay",version:HG2.version,model:"gpt-5.6-luna",reasoningEffort:"low",site:fG2,theme:kT,presets:{core:WG2,default:KG2,full:Aow},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:Qow,capabilities:[["prompt",vM,void 0],["note",zM,{}],["link",JM,{}],["image",Gp,void 0],["topics",MH0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",owA,{memoryVisibility:"shared"}],["docs",_s,void 0],["decks",bs,void 0],["agents",mW0,void 0],["assessment",sW0,void 0],["auth-service",$d,void 0],["notifications",GB0,void 0],["email-resend",KX0,void 0],["cms",NM,{}],["dashboard",gL,void 0],["directory-sync",JP,{seedContent:!0,seedContentPath:erw(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",wM,{definitions:ZG2}],["rizom-ecosystem",hM,void 0],["site-info",$M,void 0],["site-builder",QM,{}]],interfaces:[["mcp",aI,()=>({})],["discord",gb,()=>({captureUrls:!0})],["a2a",Ag,()=>({})],["webserver",cb,()=>({})],["web-chat",ey,()=>({})]],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"}}}),UG2=wow;import{readFileSync as Etw}from"fs";import{join as Ttw}from"path";import{execSync as Stw}from"child_process";import{parseArgs as Xow}from"util";var Yow={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 IG(A,Q){let w=A[Q];return typeof w==="string"?w:void 0}function sL(A,Q){let w=A[Q];return typeof w==="boolean"?w:void 0}function GG2(A){let{values:Q,positionals:w}=Xow({args:A,options:Yow,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:IG(Q,"model"),domain:IG(Q,"domain"),"content-repo":IG(Q,"content-repo"),backend:IG(Q,"backend"),"push-to":IG(Q,"push-to"),"ai-api-key":IG(Q,"ai-api-key"),"no-interactive":sL(Q,"no-interactive"),preview:sL(Q,"preview"),deploy:sL(Q,"deploy"),regen:sL(Q,"regen"),all:sL(Q,"all"),only:IG(Q,"only"),"dry-run":sL(Q,"dry-run"),"startup-check":sL(Q,"startup-check"),"storage-dir":IG(Q,"storage-dir"),yes:sL(Q,"yes"),remote:IG(Q,"remote"),token:IG(Q,"token"),outputDir:IG(Q,"outputDir")}}}Ct();import{mkdirSync as Ptw}from"fs";import{join as Mtw}from"path";import{execSync as Otw}from"child_process";var MU0={name:"@rizom/brain",version:"0.2.0-alpha.168",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 MG2,writeFileSync as gt,chmodSync as Et,existsSync as f6A,readFileSync as H6A}from"fs";import{basename as W6A,dirname as K6A,join as fB,resolve as mow}from"path";import{fileURLToPath as uow}from"url";var DG2=`ARG BUN_VERSION=1.3.10
|
|
13894
|
+
`)}})}),Q.eval.registerHandler("decideProjection",async(B)=>{let X=Urw.parse(B),Y=iwA(X.messages,X.conversationId),Z=X.existingSummary?dU2({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:$.projectionVersion,visibility:$.memoryVisibility}):null;return new oL(Q,w,$).decideProjection(Y,Z)}),Q.eval.registerHandler("retrieveMemory",async(B)=>{let X=Wrw.parse(B),Y=X.memory?nU2(Q,X.memory):Q;return new vT(Y).retrieve(X)}),Q.eval.registerHandler("buildAgentContext",async(B)=>{let X=Krw.parse(B),Y=X.memory?nU2(Q,X.memory):Q;return _U0(Y,X)}),Q.eval.registerHandler("projectMessages",async(B)=>{let X=Zrw.parse(B),Y=iwA(X.messages,X.conversationId),Z=Grw({conversationId:X.conversationId,interfaceType:X.interfaceType,channelId:X.channelId,channelName:X.channelName,messages:Y}),H=X.existingSummary?dU2({conversationId:X.conversationId,content:X.existingSummary,messageCount:X.existingMessageCount,projectionVersion:$.projectionVersion,visibility:$.memoryVisibility}):null,W=[],K=[],U=Drw({context:Q,conversation:Z,messages:Y,existing:H,upserted:W,deleted:K,projectionDecision:X.projectionDecision});return{result:await new oL(U,w,$).projectConversation(X.conversationId),summaries:W.filter((V)=>V.entityType==="summary"),decisions:W.filter((V)=>V.entityType==="decision"),actionItems:W.filter((V)=>V.entityType==="action-item"),deleted:K}}),Q.eval.registerHandler("projectConversation",async(B)=>{let X=Yrw.parse(B);return new oL(Q,w,$).projectConversation(X.conversationId)})}function dU2(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 iwA(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 Grw(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 Drw(A){let Q=FG(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 nU2(A,Q){let w=Q.map(qrw),$=w.map((B,X)=>({entity:B,score:Q[X]?.score??1,excerpt:Q[X]?.excerpt??RT(B)}));return{...A,entityService:{...A.entityService,search:async()=>$,listEntities:async({entityType:B})=>w.filter((X)=>X.entityType===B)}}}function qrw(A){if(A.entityType==="summary")return zrw(A);if(A.entityType==="decision")return Vrw(A);return Jrw(A)}function nwA(A){let Q=A.updated??"2026-01-01T00:00:00.000Z";return{id:A.id,content:A.content,contentHash:b6(A.content),visibility:A.visibility,created:Q,updated:Q}}function zrw(A){return{...nwA(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 Vrw(A){return{...nwA(A),entityType:"decision",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:FG(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 Jrw(A){let Q=A.status==="done"||A.status==="dropped"?A.status:"open";return{...nwA(A),entityType:"action-item",metadata:{conversationId:A.conversationId,channelId:A.channelId,...A.channelName?{channelName:A.channelName}:{},interfaceType:A.interfaceType,spaceId:FG(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 tU2={name:"@brains/conversation-memory",version:"0.2.0-alpha.169",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 Irw=new zK,brw=new NT,Lrw=new jT,krw=f.object({conversationId:f.string()});class rwA extends fw{entityType=aB;schema=Mt;adapter=Irw;constructor(A={}){super(GU0,tU2,A,mwA)}getConfig(){return this.config}getTemplates(){return{"summary-list":LU2,"summary-detail":kU2,"ai-response":_U2}}getDataSources(){return[new lwA(this.logger.child("SummaryDataSource"))]}getDerivedEntityProjections(A){if(!this.config.enableProjection)return[];return[{id:"conversation-memory-projection",targetType:aB,job:{type:UU2,handler:new FU0(A,this.logger,this.config)},initialSync:{shouldEnqueue:async()=>A.spaces.length>0&&!await M_(A,aB,{outputVisibility:this.config.memoryVisibility}),jobData:{mode:"rebuild-all",reason:"initial-sync"},jobOptions:{source:gwA,deduplication:"coalesce",deduplicationKey:"conversation-memory:rebuild-all:initial-sync",metadata:{operationType:"data_processing",operationTarget:"conversation-memory:rebuild-all",pluginId:GU0}}},sourceChange:{sourceKind:Uu,sourceTypes:[Uu],shouldEnqueue:(Q)=>this.shouldEnqueueConversationProjection(A,Q),events:[QR],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:gwA,deduplication:"skip",deduplicationKey:`conversation-memory:${w}`,metadata:{operationType:"data_processing",operationTarget:`conversation-memory:${w}`,pluginId:GU0}}}}}]}parseConversationMessagePayload(A){return krw.parse(A)}async shouldEnqueueConversationProjection(A,Q){let{conversationId:w}=this.parseConversationMessagePayload(Q),$=await A.conversations.get(w);if(!$)return!1;return nM({conversation:$,spaces:A.spaces}).eligible}async onRegister(A){A.entities.register(RH,Ot,brw),A.entities.register(qK,xt,Lrw),PU2({context:A,pluginId:this.id}),OU2({context:A,pluginId:this.id}),SU2({context:A,pluginId:this.id}),cU2({context:A,pluginId:this.id,config:this.config}),pwA(A),aU2({context:A,logger:this.logger,config:this.config})}}function owA(A={}){return new rwA(A)}fA();C0();C0();H5();var eU2=f.object({label:f.string(),href:f.string()}),AG2=f.object({label:f.string(),title:f.string(),detail:f.string()}),_rw=f.object({eyebrow:f.string(),name:f.string(),sub:f.string()}),Nrw=f.object({tone:f.enum(["capture","synthesis","share"]),title:f.string(),text:f.string()}),swA=f.object({captures:f.number(),links:f.number(),topics:f.number(),summaries:f.number(),peers:f.number()}),hT=f.object({eyebrow:f.string(),headline:f.string(),intro:f.string(),primaryCta:eU2,secondaryCta:eU2,inputs:f.array(AG2).min(1),outputs:f.array(AG2).min(1),core:_rw,legend:f.array(Nrw).min(1)}),awA=hT.extend({counts:swA}),QG2={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."}]},wG2=new Y6(hT,{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 jU0(A){return wG2.parse(A)}function $G2(A){return wG2.format(A)}C0();var jrw=f.looseObject({query:f.object({routeId:f.string().default("home"),sectionId:f.string().default("diagram")}).default({routeId:"home",sectionId:"diagram"})}),Prw={captures:"note",links:"link",topics:"topic",summaries:"summary",peers:"agent"};class twA{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 $=jrw.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 QG2;return hT.parse(jU0($.content))}async fetchCounts(A){let Q=await Promise.all(Object.entries(Prw).map(async([w,$])=>[w,await this.countOrZero(A,$)]));return swA.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 BG2=f.object({label:f.string(),href:f.string()}),Mrw=f.object({label:f.string(),value:f.string(),note:f.string()}),Orw=f.object({eyebrow:f.string(),headline:f.string(),intro:f.string(),primaryCta:BG2,secondaryCta:BG2,signals:f.array(Mrw)}),xrw=f.object({phase:f.string(),title:f.string(),text:f.string()}),Rrw=f.object({eyebrow:f.string(),title:f.string(),intro:f.string(),steps:f.array(xrw)}),vrw=f.object({label:f.string(),title:f.string(),text:f.string()}),hrw=f.object({title:f.string(),intro:f.string(),cards:f.array(vrw)}),Crw=f.object({title:f.string(),intro:f.string(),points:f.array(f.string())}),yrw={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."]},grw="font-body text-[15px] text-theme-muted transition-colors hover:text-theme";function XG2({href:A,label:Q}){return b1("a",{href:A,className:grw,children:Q},void 0,!1,void 0,this)}function Erw({siteInfo:A,children:Q}){let w=[...A.navigation.primary,...A.navigation.secondary],$=A.cta??{buttonText:"Start here",buttonLink:"/about"};return b1(N2A,{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(XG2,{...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(XG2,{...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 Trw=({sections:A,siteInfo:Q})=>b1(Erw,{siteInfo:Q,children:A},void 0,!1,void 0,this);function Srw({eyebrow:A,headline:Q,intro:w,primaryCta:$,secondaryCta:B,signals:X}){return b1(IT,{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(ta,{href:$.href,size:"lg",variant:"primary-strong",children:$.label},void 0,!1,void 0,this),b1(ta,{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 mrw({eyebrow:A,title:Q,intro:w,steps:$}){return b1(IT,{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 urw({title:A,intro:Q,cards:w}){return b1(IT,{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 crw({title:A,intro:Q,points:w}){return b1(IT,{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 lrw=(A)=>{switch(A){case"capture":return"bg-accent";case"synthesis":return"bg-secondary";case"share":return"bg-accent-bright"}},prw=(A)=>new Intl.NumberFormat("en",{notation:A>999?"compact":"standard"}).format(A),ht=(A,Q,w=`${Q}s`)=>`${prw(A)} ${A===1?Q:w}`;function irw({eyebrow:A,headline:Q,intro:w,primaryCta:$,secondaryCta:B,inputs:X,outputs:Y,core:Z,legend:H,counts:W}){let K=[{key:"captures",className:"top-[-10px] left-1/2 -translate-x-1/2",label:ht(W.captures,"capture")},{key:"topics",className:"top-1/2 right-[-28px] -translate-y-1/2",label:ht(W.topics,"topic")},{key:"peers",className:"bottom-[-10px] left-1/2 -translate-x-1/2",label:ht(W.peers,"peer brain")},{key:"summaries",className:"top-1/2 left-[-28px] -translate-y-1/2",label:ht(W.summaries,"summary","summaries")}];return b1(IT,{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(ta,{href:$.href,size:"lg",variant:"primary-strong",children:$.label},void 0,!1,void 0,this),b1(ta,{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((U)=>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:U.label},void 0,!1,void 0,this),b1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),b1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this),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),K.map((U)=>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 ${U.className}`,children:U.label},U.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:[ht(W.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((U)=>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:U.label},void 0,!1,void 0,this),b1("h2",{className:"mt-1.5 font-display text-[18px] font-medium text-theme",children:U.title},void 0,!1,void 0,this),b1("p",{className:"mt-1 font-body text-[13px] leading-[1.5] text-theme-muted",children:U.detail},void 0,!1,void 0,this)]},`${U.label}-${U.title}`,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this),b1("div",{className:"mt-14 grid gap-4 border-t border-theme-light pt-8 md:grid-cols-3",children:H.map((U)=>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 ${lrw(U.tone)}`},void 0,!1,void 0,this),U.title]},void 0,!0,void 0,this),b1("p",{className:"mt-1.5 font-body text-[13px] leading-[1.6] text-theme-muted",children:U.text},void 0,!1,void 0,this)]},U.title,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}var drw=s1({name:"home-diagram",description:"Relay homepage system diagram with live entity counts",schema:awA,formatter:{parse:(A)=>awA.parse({...jU0(A),counts:{captures:0,links:0,topics:0,summaries:0,peers:0}}),format:(A)=>$G2(hT.parse(A))},dataSourceId:"relay-site:home-counts",requiredPermission:"public",layout:{component:irw}}),nrw=(A)=>Srw(Orw.parse(A)),rrw=(A)=>mrw(Rrw.parse(A)),orw=(A)=>urw(hrw.parse(A)),srw=(A)=>crw(Crw.parse(A)),YG2={type:"object",label:"CTA",fields:{label:{type:"string",label:"Label"},href:{type:"string",label:"Href"}}},ZG2={namespace:"relay-site",sections:{"home-hero":{title:"Home hero",description:"Relay homepage hero section",layout:nrw,fields:{eyebrow:{type:"string",label:"Eyebrow"},headline:{type:"string",label:"Headline"},intro:{type:"string",label:"Intro"},primaryCta:{...YG2,label:"Primary CTA"},secondaryCta:{...YG2,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:rrw,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:orw,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:srw,fields:{title:{type:"string",label:"Title"},intro:{type:"string",label:"Intro"},points:{type:"array",label:"Points",minItems:1,items:{type:"string",label:"Point"}}}}}},arw=[{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:yrw}]}],fG2=HU2({packageName:"@brains/relay/site",themeProfile:"studio",layout:Trw,routes:arw,runtime:{contentNamespace:"relay-site",templates:{"home-diagram":drw},dataSources:[new twA]}});var HG2={name:"@brains/relay",version:"0.2.0-alpha.169",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 WG2=["prompt","directory-sync","note","link","topics","conversation-memory","agents","assessment","auth-service","notifications","email-resend","cms","dashboard","mcp","webserver","web-chat","discord","a2a"],KG2=[...WG2,"image","site-info","site-content","site-builder"],Aow=[...KG2,"docs","decks"],Qow=["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."],wow=UI({name:"relay",version:HG2.version,model:"gpt-5.6-luna",reasoningEffort:"low",site:fG2,theme:kT,presets:{core:WG2,default:KG2,full:Aow},evalDisable:["webserver","web-chat","mcp","discord"],agentInstructions:Qow,capabilities:[["prompt",vM,void 0],["note",zM,{}],["link",JM,{}],["image",Gp,void 0],["topics",MH0,{includeEntityTypes:["note","link","summary","agent","swot","deck","doc","anchor-profile","brain-character"],extractableStatuses:["published","draft"]}],["conversation-memory",owA,{memoryVisibility:"shared"}],["docs",_s,void 0],["decks",bs,void 0],["agents",mW0,void 0],["assessment",sW0,void 0],["auth-service",$d,void 0],["notifications",GB0,void 0],["email-resend",KX0,void 0],["cms",NM,{}],["dashboard",gL,void 0],["directory-sync",JP,{seedContent:!0,seedContentPath:erw(import.meta.dir,"..","seed-content"),initialSync:!0}],["site-content",wM,{definitions:ZG2}],["rizom-ecosystem",hM,void 0],["site-info",$M,void 0],["site-builder",QM,{}]],interfaces:[["mcp",aI,()=>({})],["discord",gb,()=>({captureUrls:!0})],["a2a",Ag,()=>({})],["webserver",cb,()=>({})],["web-chat",ey,()=>({})]],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"}}}),UG2=wow;import{readFileSync as Etw}from"fs";import{join as Ttw}from"path";import{execSync as Stw}from"child_process";import{parseArgs as Xow}from"util";var Yow={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 IG(A,Q){let w=A[Q];return typeof w==="string"?w:void 0}function sL(A,Q){let w=A[Q];return typeof w==="boolean"?w:void 0}function GG2(A){let{values:Q,positionals:w}=Xow({args:A,options:Yow,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:IG(Q,"model"),domain:IG(Q,"domain"),"content-repo":IG(Q,"content-repo"),backend:IG(Q,"backend"),"push-to":IG(Q,"push-to"),"ai-api-key":IG(Q,"ai-api-key"),"no-interactive":sL(Q,"no-interactive"),preview:sL(Q,"preview"),deploy:sL(Q,"deploy"),regen:sL(Q,"regen"),all:sL(Q,"all"),only:IG(Q,"only"),"dry-run":sL(Q,"dry-run"),"startup-check":sL(Q,"startup-check"),"storage-dir":IG(Q,"storage-dir"),yes:sL(Q,"yes"),remote:IG(Q,"remote"),token:IG(Q,"token"),outputDir:IG(Q,"outputDir")}}}Ct();import{mkdirSync as Ptw}from"fs";import{join as Mtw}from"path";import{execSync as Otw}from"child_process";var MU0={name:"@rizom/brain",version:"0.2.0-alpha.169",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 MG2,writeFileSync as gt,chmodSync as Et,existsSync as f6A,readFileSync as H6A}from"fs";import{basename as W6A,dirname as K6A,join as fB,resolve as mow}from"path";import{fileURLToPath as uow}from"url";var DG2=`ARG BUN_VERSION=1.3.10
|
|
13895
13895
|
FROM oven/bun:\${BUN_VERSION}-slim AS runtime
|
|
13896
13896
|
|
|
13897
13897
|
WORKDIR /app
|