@rizom/brain 0.2.0-alpha.507 → 0.2.0-alpha.508
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 +42 -42
- package/dist/chunks/{app-xgy07var.js → app-dzs1vyjs.js} +2 -2
- package/dist/chunks/{index-r4c9qarx.js → index-5whf24k2.js} +2 -2
- package/dist/chunks/{index-xkfmxqz3.js → index-d9vfx9ar.js} +3 -3
- package/dist/chunks/{index-xkfmxqz3.js.map → index-d9vfx9ar.js.map} +1 -1
- package/dist/chunks/{index-t0ae5yhy.js → index-s6fa1vbj.js} +4 -4
- package/dist/chunks/{index-t0ae5yhy.js.map → index-s6fa1vbj.js.map} +3 -3
- package/dist/index.js +1 -1
- package/dist/model.js +41 -41
- package/dist/model.js.map +1 -1
- package/package.json +1 -1
- /package/dist/chunks/{app-xgy07var.js.map → app-dzs1vyjs.js.map} +0 -0
- /package/dist/chunks/{index-r4c9qarx.js.map → index-5whf24k2.js.map} +0 -0
|
@@ -178,7 +178,7 @@ ${n.join(`
|
|
|
178
178
|
|
|
179
179
|
${a}`:"")}function Md(e,t,n,o){let i=n.actor??{kind:"agent",agentId:"brain-agent"};return async(a,s)=>{if(o){let l={toolName:e,args:a,conversationId:n.conversationId,interfaceType:n.interfaceType,actor:i,...n.displayName!==void 0&&{displayName:n.displayName},...n.channelId!==void 0&&{channelId:n.channelId},...n.channelName!==void 0&&{channelName:n.channelName},...s?.toolCallId!==void 0&&{toolCallId:s.toolCallId}};await o.emit("tool:invoking",l)}try{let l=s?await t(a,s):await t(a);if(o){let c={toolName:e,conversationId:n.conversationId,interfaceType:n.interfaceType,actor:i,...n.displayName!==void 0&&{displayName:n.displayName},...n.channelId!==void 0&&{channelId:n.channelId},...n.channelName!==void 0&&{channelName:n.channelName},...s?.toolCallId!==void 0&&{toolCallId:s.toolCallId}};await o.emit("tool:completed",c)}return l}catch(l){if(o){let c={toolName:e,error:Ce(l),conversationId:n.conversationId,interfaceType:n.interfaceType,actor:i,...n.displayName!==void 0&&{displayName:n.displayName},...n.channelId!==void 0&&{channelId:n.channelId},...n.channelName!==void 0&&{channelName:n.channelName},...s?.toolCallId!==void 0&&{toolCallId:s.toolCallId}};await o.emit("tool:failed",c)}throw l}}}function jd(e,t="brain-agent"){return{emit:async(n,o)=>{await e.send({type:n,payload:o,sender:t,broadcast:!0}).catch(()=>{return})}}}var Od={success:!1,error:"Public retrieval unavailable"},OB=500;function NB(e){if(!xs(e))return Od;if(e.success===!0)return e;let t=e.error;return{success:!1,error:typeof t==="string"&&t.trim()?t.slice(0,OB):"Nothing public matches that request."}}var DB=new Set(["confirmed","confirmationToken","contentHash"]),zB=new Set(["content","prompt","url","from","upload","transform","sourceAttachment"]),UB=r.looseObject({success:r.literal(!0),data:r.looseObject({documentId:r.string().min(1).optional(),entityId:r.string().min(1).optional(),attachment:r.looseObject({mediaType:r.string().min(1),url:r.string().min(1),downloadUrl:r.string().min(1).optional(),previewUrl:r.string().min(1).optional(),filename:r.string().min(1).optional(),sizeBytes:r.number().nonnegative().optional(),source:r.object({entityType:r.string().optional(),entityId:r.string().optional(),attachmentType:r.string().optional()}).optional()})})});function qB(e){return typeof e==="object"&&e!==null&&"safeParse"in e&&typeof e.safeParse==="function"}function LB(e,t={}){let n={};for(let[o,i]of Object.entries(e)){if(DB.has(o))continue;if(t.toolName==="system_create"&&zB.has(o))continue;if(qB(i))n[o]=i}return n}function $B(e){let t=UB.safeParse(e);if(!t.success)return{type:"json",value:Ux(e)};let{attachment:n}=t.data.data,o={mediaType:n.mediaType,...n.filename!==void 0?{filename:n.filename}:{},...n.sizeBytes!==void 0?{sizeBytes:n.sizeBytes}:{},...gt({source:n.source})};return{type:"json",value:Ux({...t.data,data:{...t.data.data,attachment:o,artifactCard:{rendered:!0,message:"The UI has rendered this artifact as an attachment card with Open and Download controls. Do not print raw attachment URLs in the assistant response."}}})}}function FB(e){if(!xs(e))return e;if(e.success!==!0)return e;return{...e,cached:!0}}function Ux(e){if(e===void 0)return null;return qx.parse(JSON.parse(JSON.stringify(e)))}function Nd(e,t,n){Zr(t);let o=t.interfaceType===ct;if(o&&(t.actor||t.displayName||t.enableCreateUpload||t.enableCreateTransform))throw Error("Guest execution denied");let i={},a=new Map;for(let s of e){if(o&&!Vr(s))continue;let l=Md(s.name,async(c,u)=>{if(o&&!Vr(s))throw Error("Guest execution denied");let d=u?.abortSignal,m={interfaceType:t.interfaceType,actor:t.actor??{kind:"agent",agentId:"brain-agent"},...t.displayName?{displayName:t.displayName}:{},conversationId:t.conversationId,...t.channelId&&{channelId:t.channelId},...u?.toolCallId&&{toolCallId:u.toolCallId},...d&&{signal:d},...t.channelName&&{channelName:t.channelName},...t.userPermissionLevel&&{userPermissionLevel:t.userPermissionLevel},...t.isAnchor!==void 0&&{isAnchor:t.isAnchor},...o&&{userPermissionLevel:"public",isAnchor:!1}};if(s.sideEffects!=="none"){if(s.sideEffects==="writes"||s.sideEffects==="external")a.clear();return s.handler(c,m)}let p=`${s.name}:${JSON.stringify(c)}`;if(!o&&a.has(p))return FB(a.get(p));let f;try{f=o?NB(await s.handler(c,m)):await s.handler(c,m)}catch(g){if(!o)throw g;f=Od}if(o&&!xs(f))f=Od;if(!o)a.set(p,f);return f},t,o?void 0:n);i[s.name]=Ol({description:s.description,inputSchema:r.object(LB(s.inputSchema,{toolName:s.name,...t.enableCreateUpload!==void 0&&{enableCreateUpload:t.enableCreateUpload},...t.enableCreateTransform!==void 0&&{enableCreateTransform:t.enableCreateTransform}})),execute:l,toModelOutput:({output:c})=>$B(c)})}return i}function BB(e,t){return t.interfaceType===ct?e.filter(Vr):e}function GB(e){return typeof e==="object"&&e!==null&&"action"in e&&e.action==="start"}function JB(e){let t=e.steps.at(-1),n=t?.toolResults?.some((i)=>ws.safeParse(i.output).success)??!1,o=t?.toolCalls?.some((i)=>i.toolName==="playbook_manage"&&GB(i.input))??!1;return n||o}function Dd(e){let{model:t,modelId:n,webSearch:o,temperature:i,maxTokens:a,reasoningEffort:s,messageBus:l}=e,c=Oi(n),u=jd(l);return function(p){let f=Nd(p.tools,{conversationId:"",interfaceType:"agent"},u),g=new Xb({model:t,callOptionsSchema:Dx,prepareCall:({options:h,...v})=>{Zr(h),zu(h);let x=h.interfaceType===ct,_=h.disableTools?[]:BB(p.getToolsForPermission(h.userPermissionLevel),h),y=_.map((S)=>S.name),w=Nd(_,{conversationId:h.conversationId,channelId:h.channelId,channelName:h.channelName,interfaceType:h.interfaceType,actor:h.actor,displayName:h.displayName,userPermissionLevel:h.userPermissionLevel,isAnchor:h.isAnchor,enableCreateUpload:h.enableCreateUpload,enableCreateTransform:h.enableCreateTransform},u);return{...v,...x&&{messages:ss(v.messages),allowSystemInMessages:!1,providerOptions:{}},instructions:zx(p.identity,h.userPermissionLevel,p.pluginInstructions,p.profile,p.agentInstructions,h.agentContextInstructions,h.isAnchor)+(x?`
|
|
180
180
|
|
|
181
|
-
${GS}`:""),tools:w,activeTools:y,...i!==void 0&&c.supportsTemperature&&{temperature:i},...a!==void 0&&{maxTokens:a},...(c.provider==="openai"&&s!==void 0?!0:o&&!x)&&{providerOptions:{...c.provider==="openai"&&s&&{openai:{reasoningEffort:s}},...o&&!x&&{anthropic:{webSearch:!0}}}}}},tools:f,stopWhen:[JB,Ai(p.stepLimit??10)]});return{generate:async(h)=>{Zr(h.options),zu(h.options);let v=So(h.options);if(!v)return g.generate(h);let x=ss(h.messages).at(-1);if(x?.role!=="user"||typeof x.content!=="string"||!x.content.trim()||x.content.length>v.limits.messageCharacters)throw Error("Guest input limit exceeded");let _=await jx({model:t,messages:ss(h.messages),screening:h.options.guestScreening,signal:h.abortSignal}),y=_.usage?[{usage:_.usage}]:[];if(_.kind==="judged"&&_.category!=="in-scope")return{text:h.options.guestScreening?.refusal??Mx,steps:[],usage:{inputTokens:_.usage.inputTokens,outputTokens:_.usage.outputTokens,totalTokens:_.usage.totalTokens},guestSettlement:ud(y,e.guestPricing),guestScreening:{outcome:"refused",category:_.category}};let w=await g.generate(h);return Object.assign(w,{guestSettlement:ud([...y,...w.steps],e.guestPricing),guestScreening:_.kind==="judged"?{outcome:"answered"}:{outcome:"unscreened"}})}}}}async function Ts(e,t,n){let o=await e.send({type:Lx,sender:t,payload:{actor:n}});if("noop"in o)return null;if(!o.success)throw Error("Principal resolution unavailable");return $x.parse(o.data).principal}function Bx(e,t){return new Fx(e,(n)=>Ts(t,"shell:content-service",n))}var zd=et.Service("@brains/conversation-service/ConversationService");function HB(e){if(e.service){let n=e.service;return{service:n,close:()=>n.close()}}let t=Gx.createFreshFromConfig(e.logger,e.messageBus,e.dbConfig,e.config);try{return{service:t,close:()=>t.close()}}catch(n){throw t.close(),n}}function Jx(e){return hn(zd,()=>HB(e))}var Ud=et.Service("@brains/entity-service/EntityService");function VB(e){return"close"in e&&typeof e.close==="function"}function Hx(e){return hn(Ud,()=>{let t=e.service??Wx.createFresh(e);return{service:t,close:()=>{if(VB(t))t.close()}}})}var Yi=r.strictObject({dedupeKey:r.string().min(1).max(512),title:r.string().min(1),body:r.string().min(1),html:r.string().min(1).optional(),sensitivity:r.enum(["normal","secret"]).optional(),includeInInbox:r.boolean().optional()}),qd=r.strictObject({alerts:r.array(Yi).optional()});var Is="shell:recurring-check",$d=86400000,ZB=7*$d,KB=3*$d,QB=r.strictObject({checkId:r.string().min(1)}),YB=r.discriminatedUnion("kind",[r.strictObject({kind:r.literal("last-success"),checkId:r.string(),at:r.string().datetime()}),r.strictObject({kind:r.literal("alert"),checkId:r.string(),dedupeKey:r.string(),status:r.enum(["pending","suppressed","delivered","resolved"]),alert:Yi,observedAt:r.string().datetime(),includeInInbox:r.boolean().optional(),deliveredAt:r.string().datetime().optional(),resolvedAt:r.string().datetime().optional()})]);class Cs{brainId;scheduler;state;jobQueue;delivery;logger;clock;nowFallback;checks=new Map;pluginChecks=new Map;alertOperations=new Zx;handlerRegistered=!1;started=!1;stopPromise=null;constructor(e){this.brainId=e.brainId,this.scheduler=e.scheduler,this.jobQueue=e.jobQueue,this.delivery=e.delivery,this.logger=e.logger.child("RecurringCheckService"),this.clock=e.clock,this.nowFallback=e.now??(()=>new Date),this.state=e.runtimeState.scoped({namespace:"shell.recurring-checks",schema:YB});let t={validateAndParse:(n)=>{let o=QB.safeParse(n);return o.success?o.data:null},process:async(n)=>{await this.runNow(n.checkId)}};this.jobQueue.registerHandler(Is,t,"shell"),this.handlerRegistered=!0}abandon(){if(this.started)throw Error("Cannot abandon a running recurring check service");if(!this.handlerRegistered)return;this.jobQueue.unregisterHandler(Is),this.handlerRegistered=!1}namespace(e){return{register:(t)=>this.register(e,t)}}register(e,t){Vx(e,"plugin ID"),Vx(t.id,"check ID");let n=`${e}:${t.id}`;if(this.checks.has(n))throw Error(`Recurring check already registered: ${n}`);let o={pluginId:e,definition:{...t,id:n},catchUpTasks:new Set};this.checks.set(n,o);let i=this.pluginChecks.get(e)??new Set;if(i.add(o),this.pluginChecks.set(e,i),this.started)this.schedule(o),this.trackCatchUp(o).catch((a)=>{this.logger.error(`Failed to enqueue recurring check ${n}`,a)});return()=>{this.releaseRegisteredCheck(o,Error(`Recurring check unregistered: ${n}`)).catch((a)=>{this.logger.error(`Failed to unregister recurring check ${n}`,a)})}}async unregisterPlugin(e){let t=[...this.pluginChecks.get(e)??[]];await this.drainCleanupTasks(t.map((n)=>this.releaseRegisteredCheck(n,Error(`Recurring check plugin unregistered: ${e}`))))}async start(){if(this.started)return;if(this.stopPromise)await this.stopPromise,this.stopPromise=null;this.started=!0;for(let e of this.checks.values())this.schedule(e);await Promise.all([...this.checks.values()].map((e)=>this.trackCatchUp(e)))}stop(){return this.stopPromise??=this.stopChecks(),this.stopPromise}async stopChecks(){this.started=!1;let e=Error("Recurring check service stopped"),t=[...this.pluginChecks.values()].flatMap((n)=>[...n]);await this.drainCleanupTasks(t.map((n)=>n.releasePromise??this.settleRegisteredCheck(n,e)))}async runNow(e,t){t?.throwIfAborted();let n=this.checks.get(e);if(!n)throw Error(`Unknown recurring check: ${e}`);if(n.activeCheck)return this.logger.debug(`Skipping overlapping recurring check: ${e}`),!1;let o=new AbortController,i=t?AbortSignal.any([o.signal,t]):o.signal,a={controller:o,settled:Promise.resolve()};n.activeCheck=a;let s=Promise.resolve().then(()=>this.executeRegisteredCheck(n,i)),l=()=>{if(n.activeCheck===a)delete n.activeCheck};return a.settled=s.then(l,l),s}async executeRegisteredCheck(e,t){let n=e.definition.id,o,i=async(l)=>{let c=AbortSignal.any([t,l]),u=e.definition.deliverAlerts!==!1;if(u)await this.flushPendingAlerts(n);else await this.suppressPendingAlerts(n);c.throwIfAborted();let d=await e.definition.run({signal:c});c.throwIfAborted();let m=qd.parse(d);for(let p of m.alerts??[])c.throwIfAborted(),await this.recordAlert(n,p,{deliver:u,includeInInbox:p.includeInInbox??e.definition.includeInInbox!==!1});c.throwIfAborted(),await this.state.set(this.lastSuccessKey(n),{kind:"last-success",checkId:n,at:this.currentTime().toISOString()})},a=se.tryPromise({try:(l)=>(o=i(l),o),catch:(l)=>l}),s=await se.runPromiseExit(a,{signal:t});if(o)await Promise.allSettled([o]);if(ot.isSuccess(s))return!0;if(t.aborted)throw t.reason;throw Pr.squash(s.cause)}getRegisteredCheckIds(){return[...this.checks.keys()]}trackCatchUp(e){let t=this.enqueueCatchUpIfNeeded(e.definition);e.catchUpTasks.add(t);let n=()=>{e.catchUpTasks.delete(t)};return t.then(n,n),t}releaseRegisteredCheck(e,t){if(e.releasePromise)return e.releasePromise;let n=e.definition.id;if(this.checks.get(n)===e)this.checks.delete(n);let o=this.releaseRegisteredCheckOnce(e,t);return e.releasePromise=o,o}async releaseRegisteredCheckOnce(e,t){try{await this.settleRegisteredCheck(e,t)}finally{let n=this.pluginChecks.get(e.pluginId);if(n?.delete(e),n?.size===0)this.pluginChecks.delete(e.pluginId)}}async settleRegisteredCheck(e,t){let n=[];if(e.scheduledJob){let o=e.scheduledJob;delete e.scheduledJob;try{n.push(o.stop())}catch(i){n.push(Promise.reject(i))}}if(e.activeCheck)e.activeCheck.controller.abort(t),n.push(e.activeCheck.settled);n.push(...e.catchUpTasks),await this.drainCleanupTasks(n)}async drainCleanupTasks(e){let t=await Promise.allSettled(e),n=[];for(let o of t)if(o.status==="rejected")n.push(o.reason);if(n.length===1)throw n[0];if(n.length>1)throw AggregateError(n,"Recurring check cleanup failed")}schedule(e){let t=e.definition,n=Ld(this.brainId,t.id,t.cadence);e.scheduledJob=this.scheduler.scheduleCron(n.expression,async()=>{try{await this.enqueue(t.id)}catch(o){this.logger.error(`Failed to enqueue scheduled recurring check ${t.id}`,o)}},{timezone:"UTC"})}async enqueueCatchUpIfNeeded(e){let t=this.currentTime(),n=Ld(this.brainId,e.id,e.cadence),o=Kx(t,n),i=await this.state.get(this.lastSuccessKey(e.id));if(i?.kind==="last-success"&&new Date(i.at)>=o)return;await this.enqueue(e.id)}enqueue(e){let t={source:"shell",metadata:{operationType:"data_processing",operationTarget:e,silent:!0},maxRetries:3,deduplication:"skip",deduplicationKey:e};return this.jobQueue.enqueue({type:Is,data:{checkId:e},options:t})}async listOpenAlerts(){return(await this.state.list({keyPrefix:"alert:"})).flatMap((t)=>{let n=t.value;if(n.kind!=="alert"||n.status==="resolved")return[];if(!(n.includeInInbox??this.checks.get(n.checkId)?.definition.includeInInbox!==!1))return[];return[{id:t.key,checkId:n.checkId,title:n.alert.title,body:n.alert.body,observedAt:n.observedAt}]}).sort((t,n)=>t.observedAt.localeCompare(n.observedAt)||t.id.localeCompare(n.id))}async resolveOpenAlert(e){await this.alertOperations.run(e,async()=>{let t=await this.state.get(e),n=t?.kind==="alert"&&(t.includeInInbox??this.checks.get(t.checkId)?.definition.includeInInbox!==!1);if(t?.kind!=="alert"||t.status==="resolved"||!n)throw Error("Recurring-check inbox item is not open");await this.state.set(e,{...t,status:"resolved",resolvedAt:this.currentTime().toISOString()})})}async flushPendingAlerts(e){let t=await this.state.list({keyPrefix:this.alertKeyPrefix(e)});for(let n of t)await this.alertOperations.run(n.key,async()=>{let o=await this.state.get(n.key);if(o?.kind==="alert"&&(o.status==="pending"||o.status==="suppressed"))await this.deliverStoredAlert(n.key,o)})}async suppressPendingAlerts(e){let t=await this.state.list({keyPrefix:this.alertKeyPrefix(e)});for(let n of t)await this.alertOperations.run(n.key,async()=>{let o=await this.state.get(n.key);if(o?.kind==="alert"&&o.status==="pending")await this.state.set(n.key,{...o,status:"suppressed"})})}async recordAlert(e,t,n){let o=Yi.parse(t),i=this.alertKey(e,o.dedupeKey);await this.alertOperations.run(i,async()=>{let a=await this.state.get(i);if(a?.kind==="alert"){let l=a.includeInInbox===n.includeInInbox?a:{...a,includeInInbox:n.includeInInbox};if(l!==a)await this.state.set(i,l);if(l.status==="delivered"||l.status==="resolved")return;if(n.deliver)await this.deliverStoredAlert(i,l);return}let s={kind:"alert",checkId:e,dedupeKey:o.dedupeKey,status:n.deliver?"pending":"suppressed",alert:o,observedAt:this.currentTime().toISOString(),includeInInbox:n.includeInInbox};if(await this.state.set(i,s),n.deliver)await this.deliverStoredAlert(i,s)})}async deliverStoredAlert(e,t){if(await this.delivery.deliver(t.alert)===!1)return;await this.state.set(e,{...t,status:"delivered",deliveredAt:this.currentTime().toISOString()})}currentTime(){return this.clock?new Date(this.clock.currentTimeMillisUnsafe()):this.nowFallback()}lastSuccessKey(e){return`run:${yn(e)}`}alertKeyPrefix(e){return`alert:${yn(e)}:`}alertKey(e,t){return`${this.alertKeyPrefix(e)}${yn(t)}`}}function Ld(e,t,n){let o=n==="daily"?$d:ZB,i=o/60000,a=yn(`${e}\x00${t}\x00${n}`),s=Number.parseInt(a.slice(0,12),16)%i,l=s%60,c=Math.floor(s/60),u=c%24;return{expression:n==="daily"?`${l} ${u} * * *`:`${l} ${u} * * ${Math.floor(c/24)}`,offsetMs:s*60000,periodMs:o,anchorMs:n==="daily"?0:KB}}function Kx(e,t){let n=e.getTime(),o=n-t.anchorMs,a=t.anchorMs+Math.floor(o/t.periodMs)*t.periodMs+t.offsetMs;if(a>n)a-=t.periodMs;return new Date(a)}function Vx(e,t){if(!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(e))throw Error(`Invalid recurring-check ${t}: ${e}. Use 1-64 alphanumeric, _, or - characters.`)}var $e=Qx("runtime_state_records",{namespace:ks("namespace").notNull(),key:ks("key").notNull(),value:ks("value",{mode:"json"}).notNull(),createdAt:Fd("created_at").notNull(),updatedAt:Fd("updated_at").notNull()},(e)=>({pk:Xx({columns:[e.namespace,e.key]}),namespaceUpdatedAtIdx:Yx("idx_runtime_state_namespace_updated_at").on(e.namespace,e.updatedAt)}));function tT(e){return eT({url:e.url,schema:{runtimeStateRecords:$e},authToken:e.authToken,authTokenEnv:"RUNTIME_STATE_DATABASE_AUTH_TOKEN"})}var XB=/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/,aT=512;class Gd{db;namespace;schema;now;constructor(e,t,n,o=()=>new Date){eG(t),this.db=e,this.namespace=t,this.schema=n,this.now=o}async get(e){let t=Bn(e),o=(await this.db.select().from($e).where(Gn(nr($e.namespace,this.namespace),nr($e.key,t))).limit(1))[0];if(!o)return null;return this.schema.parse(o.value)}async has(e){let t=Bn(e);return(await this.db.select({key:$e.key}).from($e).where(Gn(nr($e.namespace,this.namespace),nr($e.key,t))).limit(1)).length>0}async set(e,t){let n=Bn(e),o=this.schema.parse(t),i=this.now().getTime();await this.db.insert($e).values({namespace:this.namespace,key:n,value:o,createdAt:i,updatedAt:i}).onConflictDoUpdate({target:[$e.namespace,$e.key],set:{value:o,updatedAt:i}})}async setIfNotExists(e,t){let n=Bn(e),o=this.schema.parse(t),i=this.now().getTime(),a=await this.db.insert($e).values({namespace:this.namespace,key:n,value:o,createdAt:i,updatedAt:i}).onConflictDoNothing({target:[$e.namespace,$e.key]});return Number(a.rowsAffected)>0}async compareAndSet(e,t,n){let o=Bn(e),i=this.schema.parse(t),a=this.schema.parse(n),s=await this.db.update($e).set({value:a,updatedAt:this.now().getTime()}).where(Gn(nr($e.namespace,this.namespace),nr($e.key,o),nr($e.value,i)));return Number(s.rowsAffected)===1}async delete(e){let t=Bn(e),n=await this.db.delete($e).where(Gn(nr($e.namespace,this.namespace),nr($e.key,t)));return Number(n.rowsAffected)>0}async list(e={}){return(await this.listRows(e)).map((n)=>({key:n.key,value:this.schema.parse(n.value),createdAt:new Date(n.createdAt),updatedAt:new Date(n.updatedAt)}))}async clear(e={}){let t=await this.db.delete($e).where(Gn(nr($e.namespace,this.namespace),rT(e.keyPrefix)));return Number(t.rowsAffected)}async listRows(e){let{keyPrefix:t,afterKey:n,limit:o}=e;if(n!==void 0)Bn(n);if(o!==void 0)r.number().int().min(1).max(1000).parse(o);let i=this.db.select({...nT($e),key:Bd`CAST(${$e.key} AS BLOB)`.mapWith((a)=>new TextDecoder("utf-8",{fatal:!0}).decode(a))}).from($e).where(Gn(nr($e.namespace,this.namespace),rT(t),n!==void 0?oT($e.key,n):void 0)).orderBy(iT($e.key)).$dynamic();return o===void 0?i:i.limit(o)}}function eG(e){if(!XB.test(e))throw Error(`Invalid runtime state namespace: ${e}. Use 1-128 alphanumeric, _, ., :, or - characters.`)}function Bn(e){if(e.length===0||e.length>aT)throw Error("Runtime state keys must be 1-512 characters long");return e}function rT(e){if(e===void 0)return;return tG(e),Bd`substr(CAST(${$e.key} AS BLOB), 1, length(CAST(${e} AS BLOB))) = CAST(${e} AS BLOB)`}function tG(e){if(e.length>aT)throw Error("Runtime state key prefixes must be 512 characters or shorter");return e}class Rs{db;client;logger;databaseUrl;walInitialization=null;walInitializationSettled=!1;closeRequested=!1;clientClosed=!1;static createFresh(e,t){return new Rs(e,t??fr.getInstance())}constructor(e,t){let{db:n,client:o,url:i}=tT(e);this.db=n,this.client=o,this.databaseUrl=i,this.logger=t.child("RuntimeStateService")}initialize(){if(this.closeRequested)return Promise.resolve();return this.walInitialization??=this.initializeWALMode(),this.walInitialization}async initializeWALMode(){try{await sT(this.client,this.databaseUrl)}catch(e){this.logger.warn("Failed to enable runtime state WAL mode (non-fatal)",e)}finally{if(this.walInitializationSettled=!0,this.closeRequested)this.closeClient()}}scoped(e){return new Gd(this.db,e.namespace,e.schema)}close(){if(this.closeRequested=!0,!this.walInitialization||this.walInitializationSettled)this.closeClient()}closeClient(){if(this.clientClosed)return;this.clientClosed=!0,this.client.close()}}var Jd=et.Service("@brains/runtime-state/RuntimeStateService");function lT(e){return hn(Jd,()=>{let t=e.service??Rs.createFresh(e.config,e.logger);return{service:t,close:()=>t.close()}})}async function Wd(e,t){if(e.status==="running"){t.warn(`Daemon already running: ${e.name}`);return}e.status="starting",delete e.error;try{await e.daemon.start(),e.status="running",e.startedAt=new Date,t.debug(`Daemon started successfully: ${e.name}`)}catch(n){throw e.status="error",e.error=Xi(n),t.warn(`Daemon ${e.name} failed to start: ${Ce(n)}`),n}}async function Hd(e,t){if(e.status==="stopped"){t.warn(`Daemon already stopped: ${e.name}`);return}e.status="stopping";try{await e.daemon.stop(),e.status="stopped",e.stoppedAt=new Date,t.debug(`Daemon stopped successfully: ${e.name}`)}catch(n){throw e.status="error",e.error=Xi(n),t.error(`Failed to stop daemon: ${e.name}`,n),n}}async function cT(e){if(!e.daemon.healthCheck)return;try{let t=await e.daemon.healthCheck();return e.health=t,t}catch(t){let n={status:"error",message:Ce(t),lastCheck:new Date};return e.health=n,n}}function uT(e){return{name:e.name,pluginId:e.pluginId,status:e.status,health:e.health}}class Es{daemons=new Map;daemonScopes=new Map;daemonTransitions=new Map;logger;static createFresh(e){return new Es(e)}constructor(e){this.logger=e.child("DaemonRegistry")}register(e,t,n){if(this.daemonScopes.has(e))throw Error(`Cannot overwrite running daemon: ${e}`);if((this.daemonTransitions.get(e)?.pending??0)>0)throw Error(`Cannot overwrite transitioning daemon: ${e}`);if(this.daemons.has(e))this.logger.warn(`Daemon already registered: ${e}, overwriting`);let o={name:e,daemon:t,pluginId:n,status:"stopped"};this.daemons.set(e,o),this.logger.debug(`Registered daemon: ${e} from plugin: ${n}`)}has(e){return this.daemons.has(e)}get(e){return this.daemons.get(e)}start(e){if(!this.daemons.has(e))return Promise.reject(Error(`Daemon not registered: ${e}`));return this.enqueueTransition(e,"start",()=>this.startDaemon(e))}async startDaemon(e){let t=this.requireDaemon(e);if(this.daemonScopes.has(e)){await Wd(t,this.logger);return}let n=se.runSync(Xe.make()),o=se.acquireRelease(se.promise(()=>Wd(t,this.logger)),()=>se.promise(()=>Hd(t,this.logger)));try{await se.runPromise(Xe.provide(o,n)),this.daemonScopes.set(e,n)}catch(i){throw await se.runPromise(Xe.close(n,ot.fail(i))),i}}stop(e){if(!this.daemons.has(e))return Promise.reject(Error(`Daemon not registered: ${e}`));return this.enqueueTransition(e,"stop",()=>this.stopDaemon(e))}async stopDaemon(e){let t=this.requireDaemon(e),n=this.daemonScopes.get(e);if(!n){await Hd(t,this.logger);return}this.daemonScopes.delete(e),await se.runPromise(Xe.close(n,ot.void))}async checkHealth(e){let t=this.daemons.get(e);if(!t)throw Error(`Daemon not registered: ${e}`);return cT(t)}getByPlugin(e){return Array.from(this.daemons.values()).filter((t)=>t.pluginId===e)}getAll(){return Array.from(this.daemons.keys())}getAllInfo(){return Array.from(this.daemons.values())}async getStatuses(){let e=this.getAllInfo();for(let t of e)if(t.daemon.healthCheck)await this.checkHealth(t.name);return e.map(uT)}unregister(e){if(!this.daemons.has(e))return this.logger.warn(`Daemon not registered: ${e}`),Promise.resolve();return this.enqueueTransition(e,"unregister",async()=>{let t=this.requireDaemon(e);if(this.daemonScopes.has(e)||t.status!=="stopped")await this.stopDaemon(e);this.daemons.delete(e),this.logger.debug(`Unregistered daemon: ${e}`)},!0)}abandon(e){let t=this.daemons.get(e);if(!t)return;if(t.status!=="stopped"||this.daemonScopes.has(e)||(this.daemonTransitions.get(e)?.pending??0)>0)throw Error(`Cannot abandon active daemon: ${e}`);this.daemons.delete(e),this.logger.debug(`Abandoned daemon registration: ${e}`)}async startPlugin(e){let t=this.getByPlugin(e);this.logger.debug(`Starting ${t.length} daemons for plugin: ${e}`);let n,o=[];for(let i of t){let a=this.daemonScopes.has(i.name);try{if(await this.start(i.name),!a)o.push(i.name)}catch(s){if(n??=Xi(s),!a)o.push(i.name)}}if(n){for(let i of o.reverse())try{await this.stop(i)}catch(a){this.logger.error(`Failed to roll back daemon: ${i}`,a)}throw n}}async stopPlugin(e){let t=this.getByPlugin(e);this.logger.debug(`Stopping ${t.length} daemons for plugin: ${e}`);for(let n of t)try{await this.stop(n.name)}catch(o){this.logger.error(`Failed to stop daemon: ${n.name}`,o)}}async clear(){this.logger.debug("Clearing all daemons");for(let e of[...this.daemons.keys()])try{await this.unregister(e)}catch(t){this.logger.error(`Failed to unregister daemon during clear: ${e}`,t)}this.logger.debug("All daemons cleared")}requireDaemon(e){let t=this.daemons.get(e);if(!t)throw Error(`Daemon not registered: ${e}`);return t}enqueueTransition(e,t,n,o=!1){let i=this.daemonTransitions.get(e);if(!i)i={tail:Promise.resolve(),lastKind:void 0,lastPromise:void 0,pending:0,terminal:!1},this.daemonTransitions.set(e,i);if(t==="start"&&i.terminal)return Promise.reject(Error(`Daemon is being unregistered: ${e}`));if(i.lastKind===t&&i.lastPromise)return i.lastPromise;if(o)i.terminal=!0;i.pending++;let a=i.tail.then(n),s=()=>{if(i.pending--,i.pending===0)this.daemonTransitions.delete(e)},l=a.then(s,s);return i.tail=l,i.lastKind=t,i.lastPromise=a,a}}var rG=r.object({projectionId:r.string().min(1),reason:r.string().min(1),openedAt:r.number().int().nonnegative(),expiresAt:r.number().int().nonnegative()}),nG=8,oG=32,iG=128,aG=5,sG=600000,lG=600000,cG=1000,uG="shell.projection-circuits";class As{operationContext;options;circuitStore;roots=new Map;reservedJobs=new Map;circuits=new Map;projections;static createFresh(e,t={}){return new As(e,t)}constructor(e,t){this.operationContext=e,this.options={maxDerivationDepth:t.maxDerivationDepth??nG,maxJobsPerRoot:t.maxJobsPerRoot??oG,maxMutationsPerRoot:t.maxMutationsPerRoot??iG,repeatedTargetLimit:t.repeatedTargetLimit??aG,retentionMs:t.retentionMs??sG,circuitOpenMs:t.circuitOpenMs??lG,maxTrackedRoots:t.maxTrackedRoots??cG,now:t.now??Date.now};for(let[n,o]of Object.entries(this.options)){if(n==="now")continue;if(typeof o!=="number"||!Number.isInteger(o)||o<=0)throw Error(`${n} must be a positive integer`)}this.circuitStore=t.runtimeState?.scoped({namespace:uG,schema:rG})}async initialize(e){if(this.projections)throw Error("Projection runtime supervisor is already initialized");if(this.projections=new Map(e.projections.map((n)=>[n.id,n])),!this.circuitStore)return;let t=this.options.now();for(let n of await this.circuitStore.list()){let o=n.value;if(o.expiresAt<=t||!this.projections.has(o.projectionId)){await this.circuitStore.delete(n.key);continue}this.circuits.set(o.projectionId,o)}}async reserveJobAdmission(e){let t=e.projectionId;if(!t)return this.createNoopJobReservation();let n=this.options.now();if(await this.prune(n),await this.requireProjection(t,n),await this.assertCircuitClosed(t,n),await this.assertDepth(e,n),e.projectionLineage.filter((u)=>u===t).length>1)await this.rejectAndOpen(t,`Projection ${t} repeats in one causal lineage`,n);let i=e.rootJobId,a=this.roots.get(i)?.jobs??0,s=this.reservedJobs.get(i)??0;if(a+s+1>this.options.maxJobsPerRoot)await this.rejectAndOpen(t,`Root ${i} exceeded projection job budget ${this.options.maxJobsPerRoot}`,n);this.reservedJobs.set(i,s+1);let l=!1,c=(u)=>{if(l)return;if(l=!0,this.releaseJobReservation(i),!u)return;let d=this.options.now(),m=this.getRootCounters(i,d);m.jobs++,m.updatedAt=d};return{commit:()=>c(!0),rollback:()=>c(!1)}}async assertMutationAdmission(e){let t=this.operationContext.current()?.provenance,n=t?.projectionId;if(!t||!n)return;let o=this.options.now();await this.prune(o),await this.requireProjection(n,o),await this.assertCircuitClosed(n,o);let i=this.getRootCounters(t.rootJobId,o);if(i.mutations++,i.updatedAt=o,i.mutations>this.options.maxMutationsPerRoot)await this.rejectAndOpen(n,`Root ${t.rootJobId} exceeded projection mutation budget ${this.options.maxMutationsPerRoot}`,o);let a=`${n}\x00${e.entityType}\x00${e.entityId}`,s=(i.targetMutations.get(a)??0)+1;if(i.targetMutations.set(a,s),s>this.options.repeatedTargetLimit)await this.rejectAndOpen(n,`Projection ${n} repeatedly mutated ${e.entityType}:${e.entityId}`,o)}async getDiagnostics(){let e=this.options.now();await this.prune(e);let t=Array.from(this.circuits.values()).sort((n,o)=>n.projectionId.localeCompare(o.projectionId)).map((n)=>({...n}));return{status:t.length>0?"unhealthy":"healthy",initialized:this.projections!==void 0,trackedRoots:this.roots.size,openCircuits:t}}async requireProjection(e,t){if(!this.projections)throw Error("Projection runtime supervisor is not initialized");let n=this.projections.get(e);if(!n)throw await this.rejectAndOpen(e,`Projection ${e} is not declared in the validated graph`,t),Error(`Projection ${e} is not declared`);return n}async assertDepth(e,t){let n=e.projectionId;if(!n)return;if(e.derivationDepth>this.options.maxDerivationDepth)await this.rejectAndOpen(n,`Projection ${n} depth ${e.derivationDepth} exceeds global maximum ${this.options.maxDerivationDepth}`,t)}async assertCircuitClosed(e,t){let n=this.circuits.get(e);if(!n)return;if(n.expiresAt<=t){this.circuits.delete(e),await this.circuitStore?.delete(e);return}throw Error(`Projection circuit ${e} is open: ${n.reason}`)}async rejectAndOpen(e,t,n){let o={projectionId:e,reason:t,openedAt:n,expiresAt:n+this.options.circuitOpenMs};this.circuits.set(e,o);try{await this.circuitStore?.set(e,o)}catch(i){throw Error(`Projection ${e} was rejected but its circuit could not be persisted`,{cause:i})}throw Error(t)}createNoopJobReservation(){return{commit:()=>{},rollback:()=>{}}}releaseJobReservation(e){let t=this.reservedJobs.get(e);if(t===void 0||t<=1){this.reservedJobs.delete(e);return}this.reservedJobs.set(e,t-1)}getRootCounters(e,t){let n=this.roots.get(e);if(n)return n;if(this.roots.size>=this.options.maxTrackedRoots){let i=Array.from(this.roots.entries()).sort(([a,s],[l,c])=>s.updatedAt-c.updatedAt||a.localeCompare(l))[0];if(i)this.roots.delete(i[0])}let o={jobs:0,mutations:0,targetMutations:new Map,updatedAt:t};return this.roots.set(e,o),o}async prune(e){for(let[t,n]of this.roots)if(e-n.updatedAt>=this.options.retentionMs)this.roots.delete(t);for(let[t,n]of this.circuits)if(n.expiresAt<=e)this.circuits.delete(t),await this.circuitStore?.delete(t)}}var dG={web:{serves:!0,executes:!1,handlerRegistrationMode:"validation-only",progressMonitorMode:"durable-reader",projectionActivation:"scheduler"},worker:{serves:!1,executes:!0,handlerRegistrationMode:"execution-only",progressMonitorMode:"durable-writer",projectionActivation:"executor"},combined:{serves:!0,executes:!0,handlerRegistrationMode:"combined",progressMonitorMode:"combined",projectionActivation:"scheduler"}};function Ps(e){return dG[e??"combined"]}var pG=20,mG=0.5,gG=0.06,fG=5;function Ms(e,t){let n=e[t];return typeof n==="string"&&n.trim().length>0?n.trim():void 0}function dT(e){return typeof e==="string"&&e.startsWith("https://")?e:void 0}function hG(e){if(typeof e!=="object"||e===null)return;let t=new Map(Object.entries(e)),n=t.get("name");if(typeof n!=="string"||!n)return;let o=dT(t.get("url"));return{name:n,...o?{url:o}:{}}}function yG({entity:e},t){let n=Ms(e.metadata,"pageTitle")??Ms(e.metadata,"title")??Ms(e.metadata,"name"),o=Ms(e.metadata,"slug")??e.id,i=t.siteBaseUrl?.replace(/^https?:\/\//,"").replace(/\/+$/,""),a=dT(e.metadata.origin),s=hG(e.metadata.brain),l=a??(i?new URL(t.urlFor(e.entityType,o),`https://${i}`).href:void 0);return{id:`${e.entityType}:${e.id}`,...n?{title:n}:{},source:e.entityType,entityType:e.entityType,entityId:e.id,...l?{url:l}:{},...s?{brain:s}:{}}}function pT(e){return async({answer:t})=>{let o=(await e.entityService.search({query:t,options:{limit:pG,minScore:mG,visibilityScope:Wt("public"),publishedOnly:!0}})).filter((a)=>e.isCitable(a.entity.entityType)),i=Math.max(...o.map((a)=>a.score));return o.filter((a)=>a.score>=i-gG).slice(0,fG).map((a)=>yG(a,e))}}function vG(e,t,n,o,i){return[js.created,js.updated,js.deleted].map((s)=>e.subscribe(s,async(l)=>{if(l.payload.entityType===t&&(n===null||l.payload.entityId===n)){await o();let c=s.replace("entity:","");i.debug(`${t} entity ${c}, cache refreshed`)}return{success:!0}}))}function mT(e,t,n,o){return vG(e,t,t,async()=>{await n(),await e.send({type:Yr.identityChanged,payload:{entityType:t},sender:"shell",broadcast:!0})},o)}async function bG(e,t,n){let o=_G(e.kind);if(!o)return null;try{let i=t.scoped({namespace:o,refKind:e.kind,routePath:""});return SG(await i.read(e.id),e)}catch(i){return n.debug("Skipped unavailable prior runtime upload",{uploadKind:e.kind,uploadId:e.id,error:Ce(i)}),null}}function _G(e){return e==="upload"?"upload":null}function SG(e,t){let{record:n,content:o}=e;if(wG(n.mediaType))return{kind:"text",filename:n.filename,mediaType:n.mediaType,content:new TextDecoder("utf-8").decode(o).replace(/^\uFEFF/,""),sizeBytes:n.sizeBytes,source:t};return{kind:"file",filename:n.filename,mediaType:n.mediaType,data:new Uint8Array(o),sizeBytes:n.sizeBytes,source:t}}function wG(e){let t=e.toLowerCase();return t.startsWith("text/")||t==="application/json"}function ST(e){let{config:t,entityService:n,logger:o,messageBus:i,aiService:a,mcpService:s,conversationService:l,runtimeUploadRegistry:c,disposables:u,executionOnly:d=!1}=e,m=vT.createFresh(n,o,t.identity);u.push(...mT(i,Zt.BRAIN_CHARACTER,()=>m.refreshCache(),o));let p=bT.createFresh(n,o,t.profile),f=_T.createFresh(o,async(_)=>{let y=await Ts(i,"shell:canonical-identity-service",_).catch(()=>null);if(!y?.canonicalId)return null;return{userId:y.userId,canonicalId:y.canonicalId,displayName:y.displayName}}),g=Dd({guestPricing:a.getConfig().model==="gpt-5.6-luna"?cd:void 0,model:a.getModel(),modelId:a.getConfig().model,webSearch:a.getConfig().webSearch,temperature:a.getConfig().temperature,maxTokens:a.getConfig().maxTokens,reasoningEffort:a.getConfig().reasoningEffort,messageBus:i}),h=Id(t.name),v=new fa(t.entityDisplay),x=Qi.createFresh(s,l,m,p,o,{agentFactory:g,canonicalIdentityResolver:f,...e.embeddingUsage?{embeddingUsage:e.embeddingUsage}:{},...t.embedding.enabled?{indexReadiness:n,guestAnswerSources:pT({entityService:n,isCitable:(_)=>v.isCitable(_),urlFor:(_,y)=>v.generateUrl(_,y),siteBaseUrl:t.siteBaseUrl})}:{},uploadAttachmentResolver:(_)=>bG(_,c,o),guestAskedBefore:async(_)=>{let y=await i.collect({type:gT,sender:"shell:agent-service",payload:_});return fT(y.flatMap((w)=>("noop"in w)||!w.success?[]:[w.data]))},agentContextProvider:async(_)=>(await i.collect({type:hT,sender:"shell:agent-service",payload:_})).flatMap((w)=>{if("noop"in w||!w.success)return[];return yT(w.data)}),...h?{assistantAgentId:h}:{},...t.agentInstructions&&{agentInstructions:t.agentInstructions}});if(u.push(...mT(i,Zt.ANCHOR_PROFILE,()=>p.refreshCache(),o)),!d)u.push(i.subscribe(Yr.identityChanged,async()=>(x.invalidateAgent(),{success:!0})));return{identityService:m,profileService:p,canonicalIdentityService:f,agentService:x}}var ea=et.Service("@brains/job-queue/JobQueueService"),Os=et.Service("@brains/job-queue/BatchJobManager"),Ns=et.Service("@brains/job-queue/JobProgressMonitor"),Ds=et.Service("@brains/job-queue/JobQueueWorker");function CT(e){return hn(ea,()=>{let t=e.service??wT.createFresh(e.config,e.logger,{...e.operationContext&&{operationContext:e.operationContext},...e.projectionAdmission&&{projectionAdmission:e.projectionAdmission},...e.handlerRegistrationMode&&{handlerRegistrationMode:e.handlerRegistrationMode}});return{service:t,close:()=>t.close()}})}function kT(e){let t=!1,n=se.gen(function*(){let o=yield*ea,i=e.batchJobManager??TT.createFresh(o,e.logger),a=e.jobProgressMonitor??IT.createFresh(o,e.messageBus,i,e.logger,e.progressMonitorMode),s=e.jobQueueWorker??xT.createFresh(o,a,e.logger,{pollInterval:100,concurrency:e.workerConcurrency,autoStart:!1,...e.onWorkerUnhealthy&&{onUnhealthy:e.onWorkerUnhealthy}},{...e.operationContext&&{operationContext:e.operationContext},...e.projectionBatchScope&&{projectionBatchScope:e.projectionBatchScope}});return et.make(Os,i).pipe(et.add(Ns,a),et.add(Ds,s))});return{layer:Xr.effectContext(se.acquireRelease(n,(o)=>t?se.void:xG(o))),abandon:()=>{t=!0}}}function xG(e){let t=et.get(e,Ds),n=et.get(e,Ns),o=et.get(e,Os);return se.gen(function*(){let i=yield*se.exit(se.tryPromise({try:()=>t.stop(),catch:(c)=>c})),a=yield*se.exit(se.tryPromise({try:()=>n.stop(),catch:(c)=>c})),s=yield*se.exit(se.tryPromise({try:async()=>{await o.stop()},catch:(c)=>c})),l=[i,a,s].find(ot.isFailure);if(l)yield*se.die(Pr.squash(l.cause))})}function TG(e,t=(n)=>process.exit(n)){return(n)=>{e.error("Job queue worker requires process restart",{reason:n,exitCode:1}),t(1)}}function zs(e){let t=se.runSyncExit(Xe.close(e,ot.void));if(ot.isFailure(t))throw Pr.squash(t.cause)}function RT(e){let t=e.operationContext??Us.createFresh(),n=se.runSync(Xe.make()),o,i;try{let a=se.runSync(Xr.buildWithScope(CT({config:e.jobQueueConfig,logger:e.logger,operationContext:t,...e.projectionAdmission&&{projectionAdmission:e.projectionAdmission},...e.handlerRegistrationMode&&{handlerRegistrationMode:e.handlerRegistrationMode},...e.dependencies?.jobQueueService&&{service:e.dependencies.jobQueueService}}),n)),s=et.get(a,ea),l=se.runSync(Xe.make());o=l;let c=kT({messageBus:e.messageBus,logger:e.logger,operationContext:t,...e.projectionBatchScope&&{projectionBatchScope:e.projectionBatchScope},onWorkerUnhealthy:TG(e.logger),workerConcurrency:e.workerConcurrency,...e.progressMonitorMode&&{progressMonitorMode:e.progressMonitorMode},...e.dependencies?.batchJobManager&&{batchJobManager:e.dependencies.batchJobManager},...e.dependencies?.jobProgressMonitor&&{jobProgressMonitor:e.dependencies.jobProgressMonitor},...e.dependencies?.jobQueueWorker&&{jobQueueWorker:e.dependencies.jobQueueWorker}});i=c;let u=se.runSync(Xr.buildWithScope(c.layer.pipe(Xr.provide(Xr.succeed(ea,s))),l)),d=et.get(u,Os),m=et.get(u,Ns),p=et.get(u,Ds),f,g=!1,h=!1;return{batchJobManager:d,jobProgressMonitor:m,jobQueueService:s,jobQueueWorker:p,closeRuntime:()=>(g=!0,f??=se.runPromise(Xe.close(l,ot.void)),f),rollbackRuntime:()=>{if(g)return;g=!0,c.abandon(),zs(l)},closeDatabase:()=>{if(h)return;h=!0,zs(n)}}}catch(a){if(o)try{i?.abandon(),zs(o)}catch(s){e.logger.warn("Failed to release partial job runtime acquisition",s)}try{zs(n)}catch(s){e.logger.warn("Failed to release partial job database acquisition",s)}throw a}}function AT(e){return{deliver:async(t)=>{if(!e.hasHandlers(Vd))return!1;let n=await e.send({type:Vd,payload:{title:t.title,body:t.body,...t.html?{html:t.html}:{}},sender:"shell.recurring-checks"});if(!("success"in n)||!n.success||!n.data)throw Error("Recurring alert delivery failed");let o=ET.safeParse(n.data);if(!o.success||o.data.status!=="sent")throw Error("Recurring alert delivery failed");return!0}}}function MT(e){return{sourceId:"recurring-checks",displayName:"Recurring checks",list:async()=>(await e.listOpenAlerts()).map((t)=>({id:t.id,title:PT(t.title,160),summary:PT(t.body,1000),receivedAt:t.observedAt,urgency:"high",actions:[{id:"resolve",label:"Dismiss",confirm:!0}]})),act:async(t,n,o)=>{if(o.permissionLevel!=="admin")throw Error("Admin permission required");if(n!=="resolve")throw Error("Invalid recurring-check inbox action");await e.resolveOpenAlert(t)}}}function PT(e,t){return e.length<=t?e:e.slice(0,t)}function jT(e,t){if(t)return t;let n={debug:Ut.DEBUG,info:Ut.INFO,warn:Ut.WARN,error:Ut.ERROR}[e.logging.level];return fr.createFresh({level:n,context:e.logging.context,format:e.logging.format==="json"?"json":"text",...e.logging.file?{logFile:e.logging.file}:{}})}function OT(e){return{apiKey:e.ai.apiKey,model:e.ai.model,temperature:e.ai.temperature,maxTokens:e.ai.maxTokens,webSearch:e.ai.webSearch,...e.ai.reasoningEffort&&{reasoningEffort:e.ai.reasoningEffort},...e.ai.imageApiKey?{imageApiKey:e.ai.imageApiKey}:{}}}function No(e){return{url:e.url,...e.authToken?{authToken:e.authToken}:{}}}function eI(e){let{config:t,dependencies:n,initializerLogger:o,lifecycle:i,processRole:a}=e;o.debug("Initializing Shell services");let s=Ps(a),l=jT(t,n?.logger),c=n?.operationContext??Us.createFresh(),u=[],d=$i.createFresh(),m=n?.embeddingService??Li.createFresh({apiKey:t.ai.apiKey,logger:l,usage:d}),p=n?.aiService??Ui.createFresh(OT(t),l),f=n?.entityRegistry??DT.createFresh(l),g=n?.messageBus??QT.createFresh(l,c),h=n?.templateRegistry??UT.createFresh(l),v=n?.dataSourceRegistry??zT.createFresh(l),x=n?.renderService??qT.createFresh(h),_=n?.daemonRegistry??Es.createFresh(l),y=n?.pluginManager??XT.createFresh(l,_),w=n?.permissionService??new _s(t.permissions,{spaces:t.spaces,entityActionFloor:(me)=>f.getEntityTypeConfig(me).actionPolicy}),S=n?.profileKindRegistry??new YT(t.profileKind),C=n?.channelRegistry??new FT,I=n?.inboxRegistry??new BT,b=n?.inboxFollowUpRegistry??new GT(l),E=n?.operationalHealthRegistry??new KT,B=n?.accountSettingsRegistry??new $T,R=n?.attachmentRegistry??JT.createFresh(),U=n?.runtimeUploadRegistry??WT.createFresh({dataDir:t.dataDir,logger:l}),z=i.buildLayer(lT({config:No(t.runtimeStateDatabase),logger:l,...n?.runtimeStateService&&{service:n.runtimeStateService}})),N=et.get(z,Jd),re=n?.projectionRuntimeSupervisor??As.createFresh(c,{runtimeState:N}),Q=n?.mcpService??ZT.createFresh(g,l),V={},L={runFreshBatchScope:(me)=>V.current?V.current.runFreshBatchScope(me):me()},de=RT({dependencies:n,jobQueueConfig:No(t.jobQueueDatabase),workerConcurrency:t.jobQueue.workerConcurrency,messageBus:g,operationContext:c,projectionBatchScope:L,projectionAdmission:re,handlerRegistrationMode:s.handlerRegistrationMode,progressMonitorMode:s.progressMonitorMode,logger:l}),{batchJobManager:ee,jobProgressMonitor:k,jobQueueService:X,jobQueueWorker:W}=de;i.addSyncFinalizer(()=>de.closeDatabase()),i.addSyncFinalizer(()=>de.rollbackRuntime());let J=n?.recurringCheckService??new Cs({brainId:t.siteBaseUrl??t.dataDir,scheduler:new HT,runtimeState:N,clock:se.runSync(NT.Clock),jobQueue:X,logger:l,delivery:AT(g)});i.addSyncFinalizer(()=>J.abandon()),I.registerSource("shell.recurring-checks",MT(J)),i.addSyncFinalizer(()=>I.unregisterPlugin("shell.recurring-checks"));let K=(me,Y)=>{if(!s.serves)return;_.register(me,Y,"shell"),i.addSyncFinalizer(()=>_.abandon(me))};K("shell:recurring-checks",{start:()=>J.start(),stop:()=>J.stop()});let D=i.buildLayer(Hx({embeddingService:m,embeddingsEnabled:t.embedding.enabled,entityRegistry:f,logger:l,jobQueueService:X,messageBus:g,mutationAdmission:re,...n?.projectionRuntime?.now&&{projectionNow:n.projectionRuntime.now},dbConfig:No(t.database),embeddingDbConfig:No(t.embeddingDatabase),...n?.entityService&&{service:n.entityService}})),F=et.get(D,Ud);V.current=F.getProjectionStore();let G=i.buildLayer(Jx({dbConfig:No(t.conversationDatabase),logger:l,messageBus:g,...n?.conversationService&&{service:n.conversationService}})),Z=et.get(G,zd);K("shell:guest-retention",VT({intervalMs:60000,logger:l,run:async()=>{await Z.deleteExpiredGuestConversations(100)}})),i.addSyncFinalizer(()=>{for(let me of u.splice(0))try{me()}catch(Y){l.warn("Failed to dispose shell subscription",Y)}});let A=n?.contentService??new LT({logger:l,entityService:F,aiService:p,templateRegistry:h,dataSourceRegistry:v,generationAuthorizer:Bx(w,g)}),{identityService:O,profileService:H,canonicalIdentityService:P,agentService:q}=ST({config:t,entityService:F,embeddingService:m,embeddingUsage:d,entityRegistry:f,logger:l,messageBus:g,aiService:p,mcpService:Q,conversationService:Z,runtimeUploadRegistry:U,disposables:u,executionOnly:!s.serves});return{logger:l,operationContext:c,projectionRuntimeSupervisor:re,disposables:u,entityRegistry:f,messageBus:g,renderService:x,daemonRegistry:_,pluginManager:y,templateRegistry:h,dataSourceRegistry:v,mcpService:Q,embeddingService:m,entityService:F,aiService:p,conversationService:Z,contentService:A,jobQueueService:X,jobQueueWorker:W,batchJobManager:ee,jobProgressMonitor:k,jobServicesLifecycle:de,permissionService:w,identityService:O,profileService:H,canonicalIdentityService:P,profileKindRegistry:S,channelRegistry:C,inboxRegistry:I,inboxFollowUpRegistry:b,operationalHealthRegistry:E,accountSettingsRegistry:B,agentService:q,attachmentRegistry:R,runtimeUploadRegistry:U,runtimeStateService:N,recurringCheckService:J}}function iI(e,t){e.register(Zd.name,Zd),t.debug("Shell system templates registered")}function aI(e,t){e.register(Zo.BASE_ENTITY_DISPLAY,{name:"base-entity-display",description:"Display template for base entities",schema:Kd,formatter:new tI,requiredPermission:"public"}),t.debug("Base entity display template registered")}function sI(e,t){e.registerEntityType(Zt.NOTE,Kd,new rI,{projectionSourceRole:"primary"}),t.debug("Fallback base entity adapter registered")}function lI(e,t){let n=new nI;e.registerEntityType(Zt.BRAIN_CHARACTER,n.schema,n,{classification:"system",projectionSource:!1,projectionSourceRole:"excluded"}),t.debug("Brain character entity support registered")}function cI(e,t){let n=new oI;e.registerEntityType(Zt.ANCHOR_PROFILE,n.schema,n,{classification:"system",projectionSourceRole:"canonical"}),t.debug("Anchor profile entity support registered")}async function uI(e){let{plugins:t,pluginManager:n,logger:o,initOptions:i}=e,a=i?.registrationContext?.executionOnly,s=a?t.filter((l)=>l.type!=="interface"):t;o.debug(`Found ${s.length} plugins to register`);for(let l of s)o.debug(`Registering plugin: ${l.id}`),n.registerPlugin(l);if(await n.initializePlugins(i?.registrationContext),a)await n.registerInterfaceChannels(t.filter((l)=>l.type==="interface"),i.registrationContext);if(!i?.registerOnly){for(let{id:l,error:c}of n.getFailedPlugins())if(n.getPlugin(l)?.requiresDaemonStartup?.())throw c}o.debug("Plugin initialization complete")}class qs{logger;config;processRole;static createFresh(e,t,n){return new qs(e,t,n)}constructor(e,t,n){this.logger=e.child("ShellInitializer"),this.config=t,this.processRole=n}registerShellTemplates(e){iI(e,this.logger)}registerBaseEntityDisplayTemplate(e){aI(e,this.logger)}registerFallbackBaseEntity(e){sI(e,this.logger)}registerBrainCharacterSupport(e){lI(e,this.logger)}registerAnchorProfileSupport(e){cI(e,this.logger)}async initializePlugins(e,t){await uI({plugins:this.config.plugins,pluginManager:e,logger:this.logger,initOptions:t})}initializeServices(e,t){return eI({config:this.config,dependencies:t,initializerLogger:this.logger,lifecycle:e,...this.processRole&&{processRole:this.processRole}})}registerJobHandlers(e,t,n){let o=pI.createFresh(t,n);e.registerHandler(dI.contentGeneration,o,"shell")}wireShell(e,t){e.pluginManager.setShell(t)}async initializeAll(e,t,n,o){this.logger.debug("Starting Shell initialization");try{if(this.registerShellTemplates(e),this.registerBaseEntityDisplayTemplate(e),this.registerBrainCharacterSupport(t),this.registerAnchorProfileSupport(t),await this.initializePlugins(n,o),!t.hasEntityType(Zt.NOTE))this.registerFallbackBaseEntity(t);this.logger.debug("Shell registration phase complete")}catch(i){throw this.logger.error("Shell initialization failed",i),i}}}function mI(){let e,t;return{promise:new Promise((o,i)=>{e=o,t=i}),resolve:(o)=>e?.(o),reject:(o)=>t?.(o)}}async function Ls(e){let n=(await se.runPromise(se.all(e.map((o)=>se.result(se.tryPromise({try:o,catch:(i)=>i}))),{concurrency:"unbounded"}))).find(gI.isFailure);if(n)throw n.failure}var Qd=r.strictObject({waveId:r.string().trim().min(1),ruleId:r.string().trim().min(1)});class Yd{ruleById;store;coordinator;getJobStatus;onDiagnostic;inputContext;executionContext;reconcileTargets;now;constructor(e){let t=new Map;for(let n of e.rules){if(t.has(n.id))throw Error(`Duplicate executable projection rule "${n.id}"`);t.set(n.id,n)}this.ruleById=t,this.store=e.store,this.coordinator=e.coordinator,this.getJobStatus=e.getJobStatus??(async()=>null),this.onDiagnostic=e.onDiagnostic,this.inputContext=e.inputContext,this.executionContext=e.executionContext,this.reconcileTargets=e.reconcileTargets,this.now=e.now}validateAndParse(e){let t=Qd.safeParse(e);return t.success?t.data:null}async onTerminalError(e,t,n){let o=Qd.parse(t);await this.coordinator.failActiveWaveWithIncident({waveId:o.waveId,ruleId:o.ruleId,jobId:n,failureReason:"Projection rule job exhausted retries"})}async process(e,t,n,o){let i=Qd.parse(e),a=this.ruleById.get(i.ruleId);if(!a)throw Error(`Projection rule "${i.ruleId}" is not executable`);let[s,l,c,u]=await Promise.all([this.store.listWaveInputs(i.waveId),this.store.listWaveRules(i.waveId),this.store.getWave(i.waveId),this.getJobStatus(t)]);if(!c)throw Error(`Projection wave "${i.waveId}" does not exist`);if(c.status!=="running"&&c.status!=="superseded")throw Error(`Projection wave "${i.waveId}" is not active`);let d=l.find((S)=>S.ruleId===i.ruleId);if(!d)throw Error(`Projection rule "${i.ruleId}" is not scheduled for wave "${i.waveId}"`);let m={waveId:i.waveId,ruleId:a.id,ruleVersion:a.version,jobId:t,attemptNumber:(u?.retryCount??0)+1,cutoffGeneration:c.cutoffGeneration};if(await this.recordDiagnostic({...m,event:"attempt-started"}),c.status==="superseded"){let S=await this.store.listPendingInputs();return await this.recordDiagnostic({...m,event:"apply-completed",applyOutcome:"superseded",highestPendingGeneration:$s(S)}),{waveId:i.waveId,ruleId:a.id,outcome:"superseded",inputFingerprint:null,changedTargets:[]}}if(await this.store.supersedeWaveIfStale(i.waveId,this.now())){let S=await this.store.listPendingInputs();return await this.recordDiagnostic({...m,event:"apply-completed",applyOutcome:"superseded",highestPendingGeneration:$s(S)}),await this.coordinator.continueAfterSupersession(i.waveId),{waveId:i.waveId,ruleId:a.id,outcome:"superseded",inputFingerprint:null,changedTargets:[]}}let p=kG(s,l,d.level),f=await a.selectInput({waveId:i.waveId,inputs:p},this.inputContext,o),g=a.fingerprint(f),h={...m,inputFingerprint:g,selectedSourceCount:CG(f,p)};await this.recordDiagnostic({...h,event:"input-selected"});let v={ruleId:a.id,ruleVersion:a.version,inputFingerprint:g},x=await this.store.getRuleMemo(v);await this.recordDiagnostic({...h,event:"memo-resolved",memoHit:x!==null});let _;if(x)_=x.writeIntents;else{await this.recordDiagnostic({...h,event:"derive-started",memoHit:!1});try{_=await a.derive(f,this.executionContext,o),await this.recordDiagnostic({...h,event:"derive-completed",memoHit:!1})}catch(S){throw await this.recordDiagnostic({...h,event:o.aborted?"derive-cancelled":"derive-failed",memoHit:!1}),S}}let y=await this.store.applyRuleResult({waveId:i.waveId,ruleId:a.id,ruleVersion:a.version,inputFingerprint:g,writeIntents:_,completedAt:this.now()}),w=await this.store.listPendingInputs();if(!y)return await this.recordDiagnostic({...h,event:"apply-completed",memoHit:x!==null,applyOutcome:"superseded",highestPendingGeneration:$s(w)}),await this.coordinator.continueAfterSupersession(i.waveId),{waveId:i.waveId,ruleId:a.id,outcome:"superseded",inputFingerprint:g,changedTargets:[]};return await this.recordDiagnostic({...h,event:"apply-completed",memoHit:x!==null,applyOutcome:"applied",highestPendingGeneration:$s(w)}),await this.reconcileTargets(y.changedTargets),await this.coordinator.advanceActiveWave(i.waveId),{waveId:i.waveId,ruleId:a.id,outcome:"applied",inputFingerprint:g,changedTargets:y.changedTargets}}async recordDiagnostic(e){if(!this.onDiagnostic)return;try{await this.onDiagnostic(e)}catch(t){this.executionContext.logger.warn("Projection diagnostics callback failed",t)}}}function CG(e,t){if(typeof e==="object"&&e!==null&&"sources"in e&&Array.isArray(e.sources))return e.sources.length;return t.length}function $s(e){if(e.length===0)return null;return e.reduce((t,n)=>Math.max(t,n.generation),e[0]?.generation??0)}function kG(e,t,n){let o=e.map((a)=>({sourceType:a.sourceType,sourceId:a.sourceId,revision:a.revision,operation:a.operation,generation:a.generation})),i=t.filter((a)=>a.status==="completed"&&a.level<n).flatMap((a)=>a.changedTargets.map((s)=>({sourceType:s.entityType,sourceId:s.entityId,revision:s.contentHash??`deleted:${s.entityType}:${s.entityId}`,operation:s.operation})));return[...o,...i]}function RG(e){switch(e.jobStatus){case"failed":return"Projection rule job exhausted retries";case"completed":return"Projection rule job completed without applying its result";case"missing":return e.rule.jobId?"Projection rule job is missing":"Projection rule has no durable job id";default:return"Projection rule job is in an unexpected terminal state"}}var Do="shell:projection-rule";class Xd{store;queue;graph;ruleById;graphFingerprint;createWaveId;beforeWaveCompletion;scheduleWakeup;onScheduledWakeupError;now;operationQueue=new fI;scheduledWakeup;constructor(e){this.store=e.store,this.queue=e.queue,this.graph=e.graph,this.ruleById=PG(e.graph,e.rules),this.graphFingerprint=MG(e.graph,e.rules),this.createWaveId=e.createWaveId,this.beforeWaveCompletion=e.beforeWaveCompletion??(async()=>{}),this.scheduleWakeup=e.scheduleWakeup??EG,this.onScheduledWakeupError=e.onScheduledWakeupError??(()=>{}),this.now=e.now}dispose(){this.cancelScheduledWakeup()}advanceActiveWave(e){return this.runExclusive(async()=>{let t=await this.store.getActiveWave();if(t?.id!==e){let o=await this.store.getWave(e);if(o?.status==="completed")return o;throw Error(`Projection wave "${e}" is not active`)}let n=await this.advanceWave(t);if(n.status==="completed")await this.startNextWaveInternal();return n})}startNextWave(){return this.runExclusive(()=>this.startNextWaveInternal())}continueAfterSupersession(e){return this.runExclusive(async()=>{let t=await this.store.getActiveWave();if(t?.id===e)throw Error(`Projection wave "${e}" was not superseded`);if(t)return this.advanceWave(t);return this.startNextWaveInternal()})}failActiveWave(e){return this.runExclusive(async()=>{if((await this.store.getActiveWave())?.id!==e)throw Error(`Projection wave "${e}" is not active`);return this.store.failWave(e,this.now())})}failActiveWaveWithIncident(e){return this.runExclusive(async()=>{let t=await this.store.getActiveWave();if(t&&t.id!==e.waveId)throw Error(`Projection wave "${e.waveId}" is not active; "${t.id}" is running`);if(!t){let n=await this.store.getWave(e.waveId);if(n?.status==="superseded")return n}return this.store.failWaveWithIncident({...e,failedAt:this.now()})})}async startNextWaveInternal(){let e=await this.store.getActiveWave();if(e){let s=await this.advanceWave(e);if(s.status==="completed")await this.startNextWaveInternal();return s}let t=await this.store.listPendingInputs();if(t.length===0)return this.cancelScheduledWakeup(),null;let n=AG(this.graph,this.ruleById,t),o=this.now();if(n>o)return this.schedulePendingWakeup(n),null;this.cancelScheduledWakeup();let i=await this.store.claimPendingWave({waveId:this.createWaveId(),graphFingerprint:this.graphFingerprint,startedAt:o});if(!i)return null;let a=await this.advanceWave(i);if(a.status==="completed")await this.startNextWaveInternal();return a}async runExclusive(e){return this.operationQueue.run(e)}schedulePendingWakeup(e){if(this.scheduledWakeup?.readyAt===e)return;this.cancelScheduledWakeup();let t={readyAt:e,cancel:()=>{}};t.cancel=this.scheduleWakeup(Math.max(0,e-this.now()),async()=>{if(this.scheduledWakeup!==t)return;this.scheduledWakeup=void 0;try{await this.startNextWave()}catch(n){this.onScheduledWakeupError(n)}}),this.scheduledWakeup=t}cancelScheduledWakeup(){this.scheduledWakeup?.cancel(),this.scheduledWakeup=void 0}async advanceWave(e){if(e.graphFingerprint!==this.graphFingerprint)throw Error(`Projection wave "${e.id}" graph fingerprint does not match the finalized graph`);let t=await this.store.listWaveRules(e.id);if(t.length===0){let s=await this.store.listWaveInputs(e.id),l=yI(this.graph,this.ruleById,s);if(l.length===0)return this.completeWave(e);await this.store.putWaveRules(e.id,l),t=await this.store.listWaveRules(e.id)}if(t.every((s)=>s.status==="completed"))return this.completeWave(e,t);let n=t.find((s)=>s.status==="failed");if(n)return this.store.failWaveWithIncident({waveId:e.id,ruleId:n.ruleId,jobId:n.jobId,failureReason:"Projection rule is in a terminal failed state",failedAt:this.now()});let o=await this.findStrandedQueuedRule(t);if(o)return this.store.failWaveWithIncident({waveId:e.id,ruleId:o.rule.ruleId,jobId:o.rule.jobId,failureReason:RG(o),failedAt:this.now()});let i=Math.min(...t.filter((s)=>s.status!=="completed").map((s)=>s.level)),a=t.filter((s)=>s.level===i&&s.status==="pending");return await Promise.all(a.map((s)=>this.enqueueRule(e.id,s))),e}async findStrandedQueuedRule(e){for(let t of e){if(t.status!=="queued")continue;if(!t.jobId)return{rule:t,jobStatus:"missing"};let n=await this.queue.getStatus(t.jobId);if(!n||n.status==="completed"||n.status==="failed")return{rule:t,jobStatus:n?.status??"missing"}}return null}async completeWave(e,t){let[n,o]=await Promise.all([this.store.listWaveInputs(e.id),t?Promise.resolve(t):this.store.listWaveRules(e.id)]);return await this.beforeWaveCompletion({waveId:e.id,sourceTypes:[...new Set(n.map((i)=>i.sourceType))].sort(),changedTargetTypes:[...new Set(o.flatMap((i)=>i.changedTargets.map((a)=>a.entityType)))].sort()}),this.store.completeWave(e.id,this.now())}async enqueueRule(e,t){let n=await this.queue.enqueue({type:Do,data:{waveId:e,ruleId:t.ruleId},options:{source:"projection-scheduler",rootJobId:`projection-wave:${e}`,metadata:{operationType:"data_processing",operationTarget:t.ruleId,silent:!0},deduplication:"coalesce",deduplicationKey:`projection-wave:${e}:${t.ruleId}`,projection:{id:t.ruleId}}});await this.store.queueWaveRule(e,t.ruleId,n)}}function EG(e,t){let n=setTimeout(()=>{t()},e);return()=>clearTimeout(n)}function AG(e,t,n){let i=yI(e,t,n).reduce((s,l)=>Math.max(s,t.get(l.ruleId)?.sourceChangeBatchDelayMs??0),0);if(i===0)return 0;return n.reduce((s,l)=>Math.max(s,l.markedAt),0)+i}function PG(e,t){let n=new Map;for(let i of t){if(n.has(i.id))throw Error(`Duplicate executable projection rule "${i.id}"`);n.set(i.id,i)}let o=new Set(e.projections.map((i)=>i.id));for(let i of o)if(!n.has(i))throw Error(`Projection "${i}" has no executable rule`);for(let i of n.keys())if(!o.has(i))throw Error(`Executable projection rule "${i}" is not in the graph`);return n}function MG(e,t){return hI({projections:e.projections,edges:e.edges,rules:[...t].sort((n,o)=>n.id.localeCompare(o.id)).map((n)=>({id:n.id,version:n.version}))})}function yI(e,t,n){let o=new Map(e.projections.map((c)=>[c.id,c])),i=vI(e,(c)=>[c.from,c.to]),a=new Set(e.projections.filter((c)=>jG(c,n)).map((c)=>c.id)),s=[...a];while(s.length>0){let c=s.flatMap((u)=>i.get(u)??[]).filter((u)=>o.has(u)&&!a.has(u));for(let u of c)a.add(u);s=[...new Set(c)].sort()}let l=OG(e,a);return[...a].map((c)=>{let u=o.get(c),d=t.get(c),m=l.get(c);if(!u||!d||m===void 0)throw Error(`Cannot plan projection rule "${c}"`);return{ruleId:c,targetType:u.targetType,level:m}}).sort((c,u)=>c.level-u.level||c.ruleId.localeCompare(u.ruleId))}function jG(e,t){return e.sources.some((n)=>{let o=new Set(n.excludeTypes??[]);return t.some((i)=>!o.has(i.sourceType)&&(n.types.includes("*")||n.types.includes(i.sourceType)))})}function OG(e,t){let n=vI(e,(a)=>t.has(a.from)?[a.to,a.from]:void 0),o=new Map,i=new Set(t);while(i.size>0){let a=[...i].filter((s)=>(n.get(s)??[]).every((l)=>o.has(l))).sort();if(a.length===0)throw Error("Reachable projection graph is not acyclic");for(let s of a){let l=(n.get(s)??[]).map((u)=>o.get(u)).filter((u)=>u!==void 0),c=l.length===0?0:Math.max(...l)+1;o.set(s,c),i.delete(s)}}return o}function vI(e,t){let n=new Map;for(let o of e.edges){let i=t(o);if(!i)continue;let[a,s]=i,l=n.get(a);if(l)l.push(s);else n.set(a,[s])}return n}async function bI(e){let t=new Xd({store:e.store,queue:e.queue,graph:e.graph,rules:e.rules,createWaveId:e.createWaveId,beforeWaveCompletion:e.beforeWaveCompletion,onScheduledWakeupError:(s)=>e.logger.error("Scheduled projection wakeup failed",s),...e.scheduleWakeup&&{scheduleWakeup:e.scheduleWakeup},now:e.now}),n=new Yd({rules:e.rules,store:e.store,coordinator:t,getJobStatus:(s)=>e.queue.getStatus(s),...e.onDiagnostic&&{onDiagnostic:e.onDiagnostic},inputContext:e.inputContext,executionContext:e.executionContext,reconcileTargets:e.reconcileTargets,now:e.now});e.queue.registerHandler(Do,n,"shell");let o=()=>{},i=()=>{};try{if(e.activationMode!=="executor"){let s=async(d)=>{if(d)await e.reconcileBatches?.();await t.startNextWave()},l,c=(d)=>{if(l)return l;let m=Promise.resolve().then(()=>s(d));l=m;let p=()=>{if(l===m)l=void 0};return m.then(p,p),m},u=async()=>{if(l)return;if(await e.store.hasActiveProjectionBatch())return;await c(!1)};o=e.setWakeup(u),await c(!0),i=(e.scheduleSweep??NG)(e.sweepIntervalMs??1000,async()=>{try{await c(!0)}catch(d){e.logger.error("Projection coordination sweep failed",d)}})}}catch(s){throw i(),o(),e.queue.unregisterHandler(Do),s}e.logger.debug("Projection runtime activated",{rules:e.rules.length,mode:e.activationMode??"scheduler"});let a=!0;return{scheduler:t,dispose:()=>{if(!a)return;a=!1,i(),o(),t.dispose(),e.queue.unregisterHandler(Do)}}}function NG(e,t){let n=setInterval(()=>{t()},e);return n.unref(),()=>clearInterval(n)}var DG=250,zG=r.object({success:r.boolean()}),UG=r.object({projectionBatch:r.object({operationId:r.string().min(1),childKey:r.string().min(1)})});class tp{config;services;lifecycle;initializer;role;hooks;constructor(e,t,n,o,i,a){this.config=e,this.services=t,this.lifecycle=n,this.initializer=o,this.role=Ps(i),this.hooks=a}async boot(e){this.services.logger.debug("Starting Shell boot");let t=this.initializer;await Ls([()=>this.services.entityService.initialize(),()=>this.services.jobQueueService.initialize?.()??Promise.resolve(),()=>this.services.runtimeStateService.initialize(),()=>this.services.conversationService.initialize?.()??Promise.resolve()]);let n={...this.config.entityDisplay!==void 0&&{entityDisplay:this.config.entityDisplay},...!this.role.serves&&{executionOnly:!0}};if(await t.initializeAll(this.services.templateRegistry,this.services.entityRegistry,this.services.pluginManager,{...e?.mode==="register-only"&&{registerOnly:!0},...Object.keys(n).length>0&&{registrationContext:n}}),this.services.profileKindRegistry.finalize(),this.services.channelRegistry.finalize(),this.services.inboxRegistry.finalize(),this.services.inboxFollowUpRegistry.finalize(),await this.services.pluginManager.finalizePluginRegistrations(),this.hooks.finalizeHttpRoutes(),await this.services.projectionRuntimeSupervisor.initialize(this.services.pluginManager.getProjectionGraphSnapshot()),t.registerJobHandlers(this.services.jobQueueService,this.services.contentService,this.services.entityService),e?.mode===void 0){let i=await bI({store:this.services.entityService.getProjectionStore(),queue:this.services.jobQueueService,setWakeup:(a)=>this.services.entityService.setProjectionWakeup(a),graph:this.services.pluginManager.getProjectionGraphSnapshot(),rules:this.services.pluginManager.getProjectionRulesSnapshot(),inputContext:this.hooks.createProjectionInputContext(),executionContext:this.hooks.createProjectionExecutionContext(),reconcileTargets:(a)=>this.services.entityService.reconcileProjectionTargets(a),beforeWaveCompletion:async(a)=>{if(!this.services.messageBus.hasHandlers(ep.waveReady))return;let s=await this.services.messageBus.collect({type:ep.waveReady,payload:a,sender:"shell"});if(s.length===0||s.some((l)=>("noop"in l)||!l.success))throw Error(`Projection wave ${a.waveId} completion was not acknowledged`)},logger:this.services.logger,createWaveId:_I,now:this.hooks.projectionRuntime?.now??Date.now,...this.hooks.projectionRuntime?.scheduleWakeup&&{scheduleWakeup:this.hooks.projectionRuntime.scheduleWakeup},...this.hooks.projectionRuntime?.onDiagnostic&&{onDiagnostic:this.hooks.projectionRuntime.onDiagnostic},...this.hooks.projectionRuntime?.scheduleSweep&&{scheduleSweep:this.hooks.projectionRuntime.scheduleSweep},...this.hooks.projectionRuntime?.sweepIntervalMs!==void 0&&{sweepIntervalMs:this.hooks.projectionRuntime.sweepIntervalMs},reconcileBatches:()=>this.services.entityService.recoverProjectionBatches(async(a,s)=>(await this.services.jobQueueService.getJobsByRootJobId(a)).flatMap((c)=>{let u=UG.safeParse(JSON.parse(c.data));if(!u.success||u.data.projectionBatch.operationId!==s)return[];return[{jobId:c.id,childKey:u.data.projectionBatch.childKey,status:c.status,terminalAt:c.completedAt}]})),activationMode:this.role.projectionActivation});this.services.disposables.push(()=>i.dispose())}if(this.services.jobQueueService.finalizeHandlerRegistrations(),this.hooks.registerCoreDataSources(),this.role.serves)this.hooks.registerSystemCapabilities();if(e?.mode==="register-only"){this.services.logger.debug("Shell boot complete (register-only mode)");return}if(!this.role.serves){await this.loadIdentityServices(),this.services.jobProgressMonitor.start(),await this.services.jobQueueWorker.start(),this.services.logger.debug("Shell boot complete (worker process)");return}let o;if(e?.mode!=="startup-check"){await this.startEarlyWebserver();let i=mI();this.services.disposables.push(this.services.messageBus.subscribe(Yr.initialSyncCompleted,async(l)=>(i.resolve(zG.safeParse(l.payload).data?.success===!0),{success:!0})));let a=await this.emitPluginsRegistered(),s=await this.services.entityService.backfillMissingEmbeddings();if(this.services.logger.debug("Queued missing embedding backfill jobs",{queued:s.queued,skipped:s.skipped}),await this.services.entityService.reprojectRegisteredGroupings(),a)o=i.promise.then(async(l)=>{if(l)return this.settleStartupContent();this.services.logger.warn("Initial sync failed; ready-state defaults are not created")}).catch((l)=>{this.services.logger.error("Failed to settle startup content",l)});else await this.settleStartupContent()}else await this.prepareReadyState();if(await this.services.pluginManager.readyPlugins(),e?.mode==="startup-check"){this.services.logger.debug("Shell boot complete (startup-check mode)");return}if(await this.startRuntimeServices(),o)o.then(()=>this.startIndexReadinessMonitor()).catch((i)=>{this.services.logger.warn("Semantic index readiness monitor did not start",i)});else await this.startIndexReadinessMonitor();this.services.logger.debug("Shell boot complete")}async startEarlyWebserver(){if(!this.services.daemonRegistry.has("webserver:webserver"))return;await this.services.daemonRegistry.start("webserver:webserver"),this.services.logger.debug("Started webserver before initial sync")}async emitPluginsRegistered(){let e=await this.services.messageBus.collect({type:Yr.pluginsRegistered,payload:{timestamp:new Date().toISOString(),pluginCount:this.services.pluginManager.getAllPluginIds().length},sender:"shell"});return this.services.logger.debug("Emitted plugins registered event"),e.some((t)=>("data"in t)&&wI.safeParse(t.data).data?.initialSyncPending===!0)}async settleStartupContent(){await this.prepareReadyState(),await this.services.messageBus.send({type:Yr.startupContentSettled,payload:{timestamp:new Date().toISOString()},sender:"shell",broadcast:!0}),this.services.logger.debug("Emitted startup content settled event")}async loadIdentityServices(){await Ls([()=>this.services.identityService.refreshCache(),()=>this.services.profileService.refreshCache(),()=>this.services.canonicalIdentityService.refreshCache()]),this.services.logger.debug("Identity services loaded")}async initializeIdentityServices(){await Ls([()=>this.services.identityService.initialize(),()=>this.services.profileService.initialize(),()=>this.services.canonicalIdentityService.refreshCache()]),this.services.logger.debug("Identity services initialized")}async prepareReadyState(){await this.initializeIdentityServices();let e=await SI(this.services.templateRegistry,this.services.entityService);if(e>0)this.services.logger.debug(`Materialized ${e} prompt entities`)}async startRuntimeServices(){for(let e of["shell:recurring-checks","shell:guest-retention"])if(this.services.daemonRegistry.has(e))await this.services.daemonRegistry.start(e);if(await this.services.pluginManager.startPluginDaemons(),this.role.executes)await this.services.jobQueueWorker.start();this.services.jobProgressMonitor.start(),await this.services.batchJobManager.start()}async startIndexReadinessMonitor(){await this.lifecycle.fork(this.runIndexReadinessMonitor())}runIndexReadinessMonitor(){let{entityService:e,logger:t}=this.services;return se.tryPromise({try:(n)=>e.awaitIndexReady({intervalMs:DG,signal:n}),catch:(n)=>n}).pipe(se.tap((n)=>se.sync(()=>{if(n.degraded)t.warn("Semantic index ready with degraded embeddings",n);else t.debug("Semantic index ready",n)})),se.catch((n)=>se.sync(()=>{t.warn("Semantic index readiness monitor stopped",n)})))}}class TI{handlers=new Map;register(e,t){this.handlers.set(e,t)}unregister(e){this.handlers.delete(e)}getTypes(){return Array.from(this.handlers.keys())}async get(e,t,n){let o=this.handlers.get(e);if(!o)throw Error(`Unknown insight type: ${e}. Available: ${this.getTypes().join(", ")}`);let i=n==="public"?xI(t,{publishedOnly:!0,visibilityScope:n}):t;return o(i,n)}}function II(e){let t=new TI;return t.register("overview",qG),t.register("publishing-cadence",LG),t.register("content-health",(n,o)=>$G(n,o,e)),t}async function qG(e,t){let n=await e.getEntityCounts(t),o={},i=0;for(let{entityType:f,count:g}of n)o[f]=g,i+=g;let a=await rp(e,t),s=Date.now(),l=s-604800000,c=s-2592000000,u=0,d=0;for(let f of a){let g=new Date(f.created).getTime();if(g>=l)u++;if(g>=c)d++}let m=CI(a),p=a.filter((f)=>f.metadata.status==="published");return{entityCounts:o,totalEntities:i,recentActivity:{last7days:u,last30days:d},contentHealth:{drafts:m.length,published:p.length}}}async function LG(e,t){let n=await rp(e,t),o=new Map;for(let a of n){let s=new Date(a.created);if(isNaN(s.getTime()))continue;let l=`${s.getUTCFullYear()}-${String(s.getUTCMonth()+1).padStart(2,"0")}`,c=o.get(l);if(!c)c={},o.set(l,c);c[a.entityType]=(c[a.entityType]??0)+1}return{months:Array.from(o.entries()).sort((a,s)=>s[0].localeCompare(a[0])).map(([a,s])=>{let l=0;for(let c of Object.values(s))l+=c;return{month:a,counts:s,total:l}})}}async function $G(e,t,n){let o=await rp(e,t),i=CI(o).map((c)=>({id:c.id,entityType:c.entityType,title:typeof c.metadata.title==="string"?c.metadata.title:c.id,created:c.created})),a=Date.now(),s=a-7776000000,l=o.filter((c)=>{if(n.getEntityTypeConfig(c.entityType).binaryStorage)return!1;let u=new Date(c.updated).getTime();return!isNaN(u)&&u<s}).map((c)=>({id:c.id,entityType:c.entityType,title:typeof c.metadata.title==="string"?c.metadata.title:c.id,updated:c.updated,daysSinceUpdate:Math.floor((a-new Date(c.updated).getTime())/86400000)}));return{drafts:i,stale:l}}function CI(e){return e.filter((t)=>t.metadata.status==="draft")}async function rp(e,t){let n=e.getEntityTypes(),o=[];for(let i of n){let a=await e.listEntities({entityType:i,options:{limit:1000,filter:{visibilityScope:t}}});o.push(...a)}return o}class ta{parse;idOf;items=new Map;constructor(e,t){this.parse=e,this.idOf=t}register(e){let t=this.parse(e);this.items.set(this.keyFor(t.pluginId,this.idOf(t)),t)}unregister(e,t){if(t!==void 0){this.items.delete(this.keyFor(e,t));return}let n=`${e}:`;for(let o of this.items.keys())if(o.startsWith(n))this.items.delete(o)}list(){return Array.from(this.items.values()).sort((e,t)=>e.priority-t.priority||e.label.localeCompare(t.label))}keyFor(e,t){return`${e}:${t}`}}class np extends ta{constructor(){super((e)=>kI.parse(e),(e)=>e.url)}}class op extends ta{constructor(){super((e)=>RI.parse(e),(e)=>e.id)}}function EI(e,t){return{enqueueBatch:e.enqueueBatch.bind(e),getActiveBatches:e.getActiveBatches.bind(e),getBatchStatus:e.getBatchStatus.bind(e),getActiveJobs:t.getActiveJobs.bind(t),getRecentJobs:t.getRecentJobs.bind(t),getStatus:t.getStatus.bind(t)}}var FG=["/health","/images"],BG=new Set([AI]),GG=new Set(PI),JG=new Set(["GET","POST","PUT","DELETE"]);function MI(e){let t=[];for(let[n,{plugin:o}]of e.getAllPlugins()){let i,a;try{i=o.getWebRoutes?.()??[],a=o.getApiRoutes?.()??[]}catch(s){throw Error(`Failed to collect HTTP route declarations from plugin "${n}"`,{cause:s})}t.push({pluginId:n,webRoutes:i,apiRoutes:a})}return t}function WG(e){return BG.has(e)||FG.some((t)=>e===t||e.startsWith(`${t}/`))}function ip(e,t,n=!0){let o;try{o=new URL(e,"http://route.invalid").pathname}catch{o=void 0}if(!e.startsWith("/")||e.includes("//")||e.includes("?")||e.includes("#")||e.includes("%")||e.length>1&&e.endsWith("/")||e.trim()!==e||o!==e||n&&WG(e))throw Error(`Invalid HTTP route path "${e}" declared by plugin "${t}"`)}function jI(e,t,n){if(!e.has(t))throw Error(`Invalid HTTP route method "${t}" declared by plugin "${n}"`)}function HG(e,t){if(e!=="exact"&&e!=="prefix")throw Error(`Invalid HTTP route match "${e}" declared by plugin "${t}"`)}function VG(e,t){ip(t.path,e.pluginId);let n=t.method??"GET";jI(GG,n,e.pluginId);let o=t.match??"exact";if(HG(o,e.pluginId),typeof t.handler!=="function")throw Error(`Invalid HTTP route handler for "${t.path}" declared by plugin "${e.pluginId}"`);return Object.freeze({kind:"handler",ownerPluginId:e.pluginId,fullPath:t.path,method:n,match:o,sharedHostAdmission:t.public===!0?"admit":"deny",...t.preview===!0?{preview:!0}:{},handler:t.handler})}function ZG(e,t){ip(t.path,e.pluginId,!1);let n=`/api/${e.pluginId}${t.path}`;if(ip(n,e.pluginId),jI(JG,t.method,e.pluginId),typeof t.tool!=="string"||t.tool.trim()==="")throw Error(`Invalid HTTP route tool for "${n}" declared by plugin "${e.pluginId}"`);return Object.freeze({kind:"tool",ownerPluginId:e.pluginId,fullPath:n,method:t.method,match:"exact",sharedHostAdmission:t.public?"admit":"deny",definition:Object.freeze({...t})})}function KG(e){let t=new Map;for(let n of e){let o=`${n.method} ${n.fullPath}`,i=t.get(o);if(i!==void 0)throw Error(`HTTP route conflict for ${o} between plugins "${i}" and "${n.ownerPluginId}"; give one declaration a different method or path`);t.set(o,n.ownerPluginId)}}function QG(e){return Object.freeze(e.map((t)=>Object.freeze({ownerPluginId:t.ownerPluginId,kind:t.kind,method:t.method,fullPath:t.fullPath,match:t.match,sharedHostAdmission:t.sharedHostAdmission})))}class Fs{routes;manifest;apiRoutes;webRoutes;static createFresh(){return new Fs}constructor(){}finalize(e){if(this.routes!==void 0)throw Error("HTTP route registry has already been finalized");let t=[],n=[],o=[];for(let i of e){for(let a of i.webRoutes)t.push(VG(i,a)),n.push(Object.freeze({pluginId:i.pluginId,fullPath:a.path,definition:Object.freeze({...a})}));for(let a of i.apiRoutes){let s=ZG(i,a);t.push(s),o.push(Object.freeze({pluginId:i.pluginId,fullPath:s.fullPath,definition:s.definition}))}}return KG(t),this.routes=Object.freeze(t),this.manifest=QG(this.routes),this.webRoutes=Object.freeze(n),this.apiRoutes=Object.freeze(o),this.routes}getSnapshot(){if(this.routes===void 0)throw Error("HTTP route registry has not been finalized");return this.routes}getManifest(){if(this.manifest===void 0)throw Error("HTTP route registry has not been finalized");return this.manifest}getApiRoutes(){if(this.apiRoutes===void 0)throw Error("HTTP route registry has not been finalized");return[...this.apiRoutes]}getWebRoutes(){if(this.webRoutes===void 0)throw Error("HTTP route registry has not been finalized");return[...this.webRoutes]}}function OI(e,t){e.addFinalizer(()=>t.pluginManager.shutdownPlugins()),e.addFinalizer(()=>t.jobServicesLifecycle.closeRuntime()),e.addFinalizer(()=>t.agentService.shutdown?.()),e.addFinalizer(()=>t.daemonRegistry.unregister("shell:guest-retention")),e.addFinalizer(()=>t.daemonRegistry.unregister("shell:recurring-checks"))}var YG=r.discriminatedUnion("kind",[r.object({kind:r.literal("all")}).strict().describe("Search across all entity types"),r.object({kind:r.literal("type"),entityType:r.string().min(1).describe("Entity type to search")}).strict().describe("Search within one entity type")]),DI=r.object({query:r.string().describe("Search term"),scope:YG.describe("Structured search scope. Use { kind: 'all' } for broad search across all entity types. Use { kind: 'type', entityType } only when the user asks for a specific entity type."),limit:r.number().optional().describe("Maximum number of results"),minScore:r.number().min(0).optional().describe("Minimum relevance score. Default is 0.5; lower it only for exploratory or loose recall when weak candidates are acceptable."),includeUngenerated:r.boolean().optional().describe("Include queued/failed generation stubs in results")}),zI=r.object({entityType:r.string().describe("Entity type"),id:r.string().describe("Entity ID, slug, or title")}),UI=r.object({entityType:r.string().describe("Entity type to list"),status:r.string().optional().describe("Filter by status. Omit unless the user asks for a known status; do not invent generic statuses. For wish statuses: new, planned, in-progress, done, declined."),limit:r.number().optional().describe("Maximum number of results (default: 20)")}),XG=r.object({kind:r.literal("upload").describe("Upload ref kind"),id:r.string().min(1).describe("Upload ID")}),qI=r.object({kind:r.literal("user-message").describe("Use verbatim text already supplied by the user. The server reads the stored message; do not copy its body into tool arguments."),messageId:r.string().min(1).optional().describe("Stored user message ID in this conversation; omit for the latest user message."),boundaryMode:r.enum(["literal","lines"]).optional().describe("Use lines for standalone delimiter lines: supply marker text without newline characters. The server excludes the opening line and its line ending, and stops at the start of the closing line, preserving every byte between them, including final newlines. Omit or use literal for inline text boundaries."),startAfter:r.string().min(1).optional().describe("Exact unique opening boundary, excluded from saved text. In lines mode, supply the whole marker line WITHOUT newline characters. In literal mode, supply the exact prefix to exclude. Omit to start at the beginning of the message."),endBefore:r.string().min(1).optional().describe("Exact unique closing boundary, excluded from saved text. In lines mode, supply the whole marker line WITHOUT newline characters; preceding content newlines are preserved. In literal mode, supply the exact suffix to exclude. Omit to end at the end of the message."),contentHash:r.string().min(1).optional().describe("Internal source hash returned with the confirmation; omit on the initial request.")}).strict(),eJ=r.discriminatedUnion("kind",[r.object({kind:r.literal("text").describe("Store exact/direct user-provided content without generation"),content:r.string().min(1).describe("Literal content for a direct save request without a stored user-message source. For pasted text already in this conversation, prefer source.kind user-message with exact boundaries instead of reproducing the body here.")}).strict(),qI,r.object({kind:r.literal("url").describe("Create URL/domain-backed entities such as links"),url:r.string().min(1).describe("URL or domain to create from; preserve a bare domain as provided instead of adding a scheme.")}).strict(),r.object({kind:r.literal("upload").describe("Use extract-markdown to import upload text into a note, or preserve only when the user explicitly wants to save the uploaded file/document bytes themselves. Do not use for saving a previous assistant summary about an upload; use prior-response for that."),upload:XG.describe("Exact upload candidate object from the current conversation"),transform:r.enum(["extract-markdown","preserve"]).describe("extract-markdown imports upload text into a note-like entity; preserve saves raw uploaded bytes via the registered upload-save handler and derives the durable entity type from media type. Use preserve only for explicit file/document preservation, not for saving an assistant summary response.")}).strict(),r.object({kind:r.literal("prior-response").describe("Save a previous assistant response as durable content, especially an assistant summary or answer about an upload."),messageId:r.string().min(1).optional().describe("Stored assistant message ID; omit for latest savable")}).strict()]),tJ=r.discriminatedUnion("kind",[r.object({kind:r.literal("prompt").describe("Generate a new non-image durable entity from a broad prompt with no durable source entity. Use this for general topical social/newsletter/blog/deck generation. This branch has no source field; use prompt-from-source only after resolving a specific existing content entity."),entityType:r.string().min(1).describe("Entity type to generate from the prompt. Do not use image here; use standalone-image or cover-image."),title:r.string().optional().describe("Title for the generated entity"),prompt:r.string().min(1).describe("Prompt for creating new generated content. Do not use for saving/importing existing uploads or prior responses.")}).strict(),r.object({kind:r.literal("prompt-from-source").describe("Generate a new non-image durable entity from a specific resolved existing content entity. Use when the user asks to generate from/based on a source, including requests like 'create a newsletter based on my latest blog post'. After resolving the source with a tool result, call this operation in the same turn; do not merely say you can generate it."),entityType:r.string().min(1).describe("Entity type to generate from the source and prompt. Do not use image here; use standalone-image or cover-image."),title:r.string().optional().describe("Title for the generated entity"),source:r.object({entityType:r.string().min(1).describe("Resolved content source entity type, such as post for a newsletter from a blog post. Do not use brain-character or anchor-profile."),entityId:r.string().min(1).describe("Resolved source entity ID copied from a prior tool result or typed entity ref; never an upload id, filename, guessed slug, or future placeholder.")}).strict().describe("Existing durable source entity to ground this generation. Use only resolved entity refs, not uploads, filenames, profile/brain-character context, conversation-only context, unknown sources, or guessed sources."),prompt:r.string().min(1).describe("Prompt for creating new generated content from the resolved source. Do not use for saving/importing existing uploads or prior responses.")}).strict(),r.object({kind:r.literal("standalone-image").describe("Generate a standalone image that is not attached to another entity. Do not use this as a cover image substitute; requested covers require cover-image after the target entity exists."),title:r.string().optional().describe("Title for the generated image"),prompt:r.string().min(1).describe("Prompt for creating an unattached image. Not for cover images requested for a generated post/entity.")}).strict(),r.object({kind:r.literal("cover-image").describe("Generate an image and attach it to an existing entity as coverImageId. Use only after the target entity already exists and its real entityId is known; do not use in the same initial turn as generating that target entity."),target:r.object({entityType:r.string().min(1).describe("Existing target entity type. Use the actual type of the entity being covered: social-post for LinkedIn/social posts, post for blog posts, etc."),entityId:r.string().min(1).describe("Existing target entity ID copied from a prior tool result or typed entity ref; never a placeholder or guessed future id")}).strict().describe("Existing entity that should receive the generated coverImageId"),title:r.string().optional().describe("Title for the generated image"),prompt:r.string().min(1).describe("Prompt for creating the cover image")}).strict(),r.object({kind:r.literal("attachment").describe("Generate a deterministic durable artifact from an existing entity attachment provider"),source:r.object({entityType:r.string().min(1).describe("Source entity type"),entityId:r.string().min(1).describe("Canonical source entity ID copied from a prior tool result or typed entity ref; never an upload id, filename, guessed slug, or future placeholder")}).strict().describe("Existing durable entity whose attachment provider should render the artifact. Use only resolved entity refs, not uploads or conversation-only context."),attachmentType:r.string().min(1).describe('Source artifact type such as "carousel", "printable", or "og-image"'),title:r.string().optional().describe("Title for the generated artifact"),replace:r.boolean().optional().describe("Set true for regenerate, replace, refresh, or update requests so a deterministic artifact is regenerated instead of reused")}).strict()]),LI=r.object({entityType:r.string().describe("Entity type to create. Use wish for explicitly saved or tracked unmet requested capabilities or outcomes."),title:r.string().optional().describe("Title for a new entity."),visibility:NI.optional().describe("Content visibility. Omit for public. Use shared for team/collaborator content readable by Trusted and Admin callers. Use restricted for private/admin-only content."),source:eJ.describe("Concrete source selector. Use exactly one source branch. For AI generation or source-derived artifacts, use system_generate instead."),replace:r.boolean().optional().describe("Create a new copy intentionally"),confirmed:r.literal(!0).optional().describe("Confirm the creation"),confirmationToken:r.string().optional().describe("Internal confirmation token returned by the confirmation flow")}).strict(),$I=r.object({operation:tJ.describe("Generation operation selector. Use prompt for broad non-image AI-generated entities with no source, prompt-from-source for generation from a resolved existing entity, standalone-image for unattached images, cover-image for generated covers on existing entities, and attachment for deterministic source-derived artifacts; for regenerate/replace/refresh artifact requests use attachment with replace:true."),confirmed:r.literal(!0).optional().describe("Confirm generation"),confirmationToken:r.string().optional().describe("Internal confirmation token returned by the confirmation flow")}).strict(),rJ=r.object({oldText:r.string().min(1).describe("Exact text occurring once in the original stored Markdown. Include enough context to be unique."),newText:r.string().describe("Literal replacement text; empty string deletes oldText.")}).strict(),ap=r.object({entityType:r.string().describe("Entity type"),id:r.string().describe("Entity ID, slug, or title"),fields:r.record(r.string(),r.unknown()).optional().describe("Partial frontmatter fields to update. Use this for status, title, coverImageId, ogImageId, and metadata changes such as approving an agent. To set an existing image as an entity cover, update fields.coverImageId to that image id. To remove or clear a cover image, set fields.coverImageId to null, not an empty string. Do not use fields for anchor-profile; anchor-profile updates require full markdown content replacement via content."),content:r.string().optional().describe("Full replacement text you wrote yourself. Text without frontmatter replaces the body and keeps the stored frontmatter; text with frontmatter replaces the whole document. When the user supplied the replacement text, use source instead of copying it here. For small changes, use edits instead of regenerating the whole document."),edits:r.array(rJ).min(1).max(50).optional().describe("Preferred for small content edits, especially long notes. Exact, unique, non-overlapping replacements matched against the original Markdown, applied atomically after confirmation. Fetch the entity first. Unchanged text is preserved without regeneration."),source:qI.optional().describe("Full replacement taken verbatim from a user message, for large rewrites the user supplied. Select the text with exact boundaries instead of copying it into content. Text without frontmatter replaces the body and keeps the stored frontmatter; text with frontmatter replaces the whole document."),confirmed:r.literal(!0).optional().describe("Confirm the update"),confirmationToken:r.string().optional().describe("Internal confirmation token returned by the confirmation flow"),contentHash:r.string().optional().describe("Content hash for optimistic concurrency")}),FI=r.object({entityType:r.string().describe("Entity type"),id:r.string().describe("Entity ID"),confirmed:r.literal(!0).optional().describe("Confirm the deletion"),confirmationToken:r.string().optional().describe("Internal confirmation token returned by the confirmation flow")}),Mee=r.object({entityType:r.string().describe("Entity type to extract"),source:r.string().optional().describe("Source entity ID \u2014 omit for batch"),mode:r.enum(["derive","rebuild"]).optional().describe("Batch mode: project incrementally or rebuild from scratch"),confirmed:r.literal(!0).optional().describe("Confirm destructive rebuild"),confirmationToken:r.string().optional().describe("Internal confirmation token returned by the confirmation flow")}),BI=r.object({batchId:r.string().optional().describe("Specific batch ID to check"),jobTypes:r.array(r.string()).optional().describe("Filter by job types")}),GI=r.object({type:r.string().describe("Type of insight to retrieve. Built-in: overview, publishing-cadence, content-health. Plugins may register additional types.")}),nJ=r.object({entityType:r.string().optional(),entityId:r.string().optional(),attachmentType:r.string().optional()}),oJ=r.object({mediaType:r.string(),url:r.string(),downloadUrl:r.string().optional(),previewUrl:r.string().optional(),filename:r.string().optional(),sizeBytes:r.number().optional(),source:nJ.optional()}),jee=r.object({entityId:r.string().optional(),status:r.enum(["created","generating"]),jobId:r.string().optional(),attachment:oJ.optional()}),Oee=r.object({status:r.literal("extracting"),jobId:r.string(),entityType:r.string(),source:r.string().optional(),mode:r.enum(["derive","rebuild"]).optional()});function Mr(e,t,n,o){try{e.permissionService.assertEntityActionAllowed(t,n,o.userPermissionLevel);return}catch(i){if(i instanceof JI||i instanceof Error)return{success:!1,error:i.message};throw i}}async function Gs(e,t,n){let o=n.conversationId??n.channelId;if(!o)return{success:!1,error:"Conversation message is not accessible in this conversation or does not exist."};let i=await e.conversationService.getMessages(o,{limit:100}),a=t.kind==="user-message",s=a?i.filter((p)=>{if(p.role!=="user")return!1;let f=n.userPermissionLevel??"public";if(f==="admin")return!0;let g=Bs(p.metadata)?.userPermissionLevel;return(g==="public"||g==="trusted"||g==="admin")&&e.permissionService.hasPermission(f,g)}):i.filter(WI),l=t.messageId?s.find((p)=>p.id===t.messageId):s.at(-1);if(!l)return{success:!1,error:"Conversation message is not accessible in this conversation or does not exist."};if(!a)return{success:!0,messageId:l.id,content:l.content};let c=(p,f,g)=>{if(p===void 0)return f;if(t.boundaryMode==="lines"){if(/[\r\n]/.test(p))return-1;let v=0,x=-1;for(let _ of l.content.split(/(?<=\n)/)){if(_.replace(/\r?\n$/,"")===p){if(x>=0)return-1;x=v+(g?_.length:0)}v+=_.length}return x}let h=l.content.indexOf(p);return h>=0&&h===l.content.lastIndexOf(p)?h+(g?p.length:0):-1},u=c(t.startAfter,0,!0),d=c(t.endBefore,l.content.length,!1);if(u<0||d<0||u>=d)return{success:!1,error:"User-message boundaries must each occur exactly once and select non-empty content in order. In lines mode, use complete marker lines without newline characters. Request clarification if the intended content cannot be selected uniquely."};let m=l.content.slice(u,d);if(t.contentHash&&t.contentHash!==yn(m))return{success:!1,error:"User-message source changed after the proposal. Request the change again and confirm the new approval."};return{success:!0,messageId:l.id,content:m}}function Js(e,t){return{...e,messageId:t.messageId,contentHash:yn(t.content)}}var iJ="system",HI=r.record(r.string(),r.unknown()),aJ=r.looseObject({fields:HI});function jr(e,t,n,o,i={}){let{visibility:a="admin",sideEffects:s}=i;return{name:`${iJ}_${e}`,description:t,inputSchema:n.shape,handler:async(l,c)=>{let u=n.safeParse(l);if(!u.success)return{success:!1,error:`Invalid input: ${u.error.issues.map((d)=>`${d.path.join(".")}: ${d.message}`).join(", ")}`};try{return await o(u.data,c)}catch(d){return{success:!1,error:Ce(d)}}},visibility:a,...s?{sideEffects:s}:{}}}async function Ws(e,t,n,o){let i={interfaceType:o.interfaceType,actor:o.actor,...o.channelId&&{channelId:o.channelId},...o.channelName&&{channelName:o.channelName}},a=await t(n,i);if(a.kind==="handled")return{kind:"handled",result:a.result};let s=a.input;if(s.visibility!==n.visibility)return{kind:"error",result:{success:!1,error:"Create interceptor changed or dropped the requested entity visibility."}};let l=Mr(e,s.entityType,"create",o);if(l)return{kind:"error",result:l};return{kind:"continue",createInput:s}}function Jn(e,t){if(e.entityRegistry.hasEntityType(t))return;let n=e.entityService.getEntityTypes();return{success:!1,error:`Entity type "${t}" is not available in this brain. Available types: ${n.join(", ")}.`}}function zo(e){let t={...e.conversationId?{conversationId:e.conversationId}:{},...e.channelId?{channelId:e.channelId}:{},...e.runId?{runId:e.runId}:{},...e.toolCallId?{toolCallId:e.toolCallId}:{}};return Object.keys(t).length>0?t:void 0}function sp(e,t){if(t.getEntityTypeConfig(e.entityType).binaryStorage)return{...e,content:`[binary ${e.entityType} data \u2014 use metadata for ${e.entityType} info]`};return e}function Wn(e){if(e===void 0)return;let t=e.trim();return t.length>0?t:void 0}function VI(e){if(e.fields!==void 0)return{...e};if(!e.content)return{};try{let t=JSON.parse(e.content),n=aJ.safeParse(t);if(n.success)return{fields:n.data.fields};let o=HI.safeParse(t);if(o.success)return{fields:o.data}}catch{}return{content:e.content}}var sJ={base:"note"};function ZI(e){return sJ[e]??e.replaceAll("-"," ")}function Hs(e){return[e.metadata.title,e.metadata.name,e.metadata.subject,e.metadata.slug].find((o)=>typeof o==="string"&&o.trim().length>0)??e.id}function KI(e){return!!e&&Object.keys(e.shape).length>0}async function QI(e,t,n){if(!n)return!1;let o=await e.conversationService.getMessages(n,{limit:100});for(let i of o){let s=Bs(i.metadata)?.attachments;if(!Array.isArray(s))continue;for(let l of s){if(!gr(l))continue;let c=l.source;if(!gr(c))continue;if(c.kind===t.kind&&c.id===t.id)return!0}}return!1}var lJ={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function cJ(e){return{summary:`Save uploaded file${e.title?` as "${e.title}"`:""}?`,preview:[`Filename: ${e.filename}`,`Media type: ${e.mediaType}`,`Entity type: ${e.entityType}`,`Visibility: ${e.visibility??"public"}`,...e.title?[`Title: ${e.title}`]:[]].join(`
|
|
181
|
+
${GS}`:""),tools:w,activeTools:y,...i!==void 0&&c.supportsTemperature&&{temperature:i},...a!==void 0&&{maxTokens:a},...(c.provider==="openai"&&s!==void 0?!0:o&&!x)&&{providerOptions:{...c.provider==="openai"&&s&&{openai:{reasoningEffort:s}},...o&&!x&&{anthropic:{webSearch:!0}}}}}},tools:f,stopWhen:[JB,Ai(p.stepLimit??10)]});return{generate:async(h)=>{Zr(h.options),zu(h.options);let v=So(h.options);if(!v)return g.generate(h);let x=ss(h.messages).at(-1);if(x?.role!=="user"||typeof x.content!=="string"||!x.content.trim()||x.content.length>v.limits.messageCharacters)throw Error("Guest input limit exceeded");let _=await jx({model:t,messages:ss(h.messages),screening:h.options.guestScreening,signal:h.abortSignal}),y=_.usage?[{usage:_.usage}]:[];if(_.kind==="judged"&&_.category!=="in-scope")return{text:h.options.guestScreening?.refusal??Mx,steps:[],usage:{inputTokens:_.usage.inputTokens,outputTokens:_.usage.outputTokens,totalTokens:_.usage.totalTokens},guestSettlement:ud(y,e.guestPricing),guestScreening:{outcome:"refused",category:_.category}};let w=await g.generate(h);return Object.assign(w,{guestSettlement:ud([...y,...w.steps],e.guestPricing),guestScreening:_.kind==="judged"?{outcome:"answered"}:{outcome:"unscreened"}})}}}}async function Ts(e,t,n){let o=await e.send({type:Lx,sender:t,payload:{actor:n}});if("noop"in o)return null;if(!o.success)throw Error("Principal resolution unavailable");return $x.parse(o.data).principal}function Bx(e,t){return new Fx(e,(n)=>Ts(t,"shell:content-service",n))}var zd=et.Service("@brains/conversation-service/ConversationService");function HB(e){if(e.service){let n=e.service;return{service:n,close:()=>n.close()}}let t=Gx.createFreshFromConfig(e.logger,e.messageBus,e.dbConfig,e.config);try{return{service:t,close:()=>t.close()}}catch(n){throw t.close(),n}}function Jx(e){return hn(zd,()=>HB(e))}var Ud=et.Service("@brains/entity-service/EntityService");function VB(e){return"close"in e&&typeof e.close==="function"}function Hx(e){return hn(Ud,()=>{let t=e.service??Wx.createFresh(e);return{service:t,close:()=>{if(VB(t))t.close()}}})}var Yi=r.strictObject({dedupeKey:r.string().min(1).max(512),title:r.string().min(1),body:r.string().min(1),html:r.string().min(1).optional(),sensitivity:r.enum(["normal","secret"]).optional(),includeInInbox:r.boolean().optional()}),qd=r.strictObject({alerts:r.array(Yi).optional()});var Is="shell:recurring-check",$d=86400000,ZB=7*$d,KB=3*$d,QB=r.strictObject({checkId:r.string().min(1)}),YB=r.discriminatedUnion("kind",[r.strictObject({kind:r.literal("last-success"),checkId:r.string(),at:r.string().datetime()}),r.strictObject({kind:r.literal("alert"),checkId:r.string(),dedupeKey:r.string(),status:r.enum(["pending","suppressed","delivered","resolved"]),alert:Yi,observedAt:r.string().datetime(),includeInInbox:r.boolean().optional(),deliveredAt:r.string().datetime().optional(),resolvedAt:r.string().datetime().optional()})]);class Cs{brainId;scheduler;state;jobQueue;delivery;logger;clock;nowFallback;checks=new Map;pluginChecks=new Map;alertOperations=new Zx;handlerRegistered=!1;started=!1;stopPromise=null;constructor(e){this.brainId=e.brainId,this.scheduler=e.scheduler,this.jobQueue=e.jobQueue,this.delivery=e.delivery,this.logger=e.logger.child("RecurringCheckService"),this.clock=e.clock,this.nowFallback=e.now??(()=>new Date),this.state=e.runtimeState.scoped({namespace:"shell.recurring-checks",schema:YB});let t={validateAndParse:(n)=>{let o=QB.safeParse(n);return o.success?o.data:null},process:async(n)=>{await this.runNow(n.checkId)}};this.jobQueue.registerHandler(Is,t,"shell"),this.handlerRegistered=!0}abandon(){if(this.started)throw Error("Cannot abandon a running recurring check service");if(!this.handlerRegistered)return;this.jobQueue.unregisterHandler(Is),this.handlerRegistered=!1}namespace(e){return{register:(t)=>this.register(e,t)}}register(e,t){Vx(e,"plugin ID"),Vx(t.id,"check ID");let n=`${e}:${t.id}`;if(this.checks.has(n))throw Error(`Recurring check already registered: ${n}`);let o={pluginId:e,definition:{...t,id:n},catchUpTasks:new Set};this.checks.set(n,o);let i=this.pluginChecks.get(e)??new Set;if(i.add(o),this.pluginChecks.set(e,i),this.started)this.schedule(o),this.trackCatchUp(o).catch((a)=>{this.logger.error(`Failed to enqueue recurring check ${n}`,a)});return()=>{this.releaseRegisteredCheck(o,Error(`Recurring check unregistered: ${n}`)).catch((a)=>{this.logger.error(`Failed to unregister recurring check ${n}`,a)})}}async unregisterPlugin(e){let t=[...this.pluginChecks.get(e)??[]];await this.drainCleanupTasks(t.map((n)=>this.releaseRegisteredCheck(n,Error(`Recurring check plugin unregistered: ${e}`))))}async start(){if(this.started)return;if(this.stopPromise)await this.stopPromise,this.stopPromise=null;this.started=!0;for(let e of this.checks.values())this.schedule(e);await Promise.all([...this.checks.values()].map((e)=>this.trackCatchUp(e)))}stop(){return this.stopPromise??=this.stopChecks(),this.stopPromise}async stopChecks(){this.started=!1;let e=Error("Recurring check service stopped"),t=[...this.pluginChecks.values()].flatMap((n)=>[...n]);await this.drainCleanupTasks(t.map((n)=>n.releasePromise??this.settleRegisteredCheck(n,e)))}async runNow(e,t){t?.throwIfAborted();let n=this.checks.get(e);if(!n)throw Error(`Unknown recurring check: ${e}`);if(n.activeCheck)return this.logger.debug(`Skipping overlapping recurring check: ${e}`),!1;let o=new AbortController,i=t?AbortSignal.any([o.signal,t]):o.signal,a={controller:o,settled:Promise.resolve()};n.activeCheck=a;let s=Promise.resolve().then(()=>this.executeRegisteredCheck(n,i)),l=()=>{if(n.activeCheck===a)delete n.activeCheck};return a.settled=s.then(l,l),s}async executeRegisteredCheck(e,t){let n=e.definition.id,o,i=async(l)=>{let c=AbortSignal.any([t,l]),u=e.definition.deliverAlerts!==!1;if(u)await this.flushPendingAlerts(n);else await this.suppressPendingAlerts(n);c.throwIfAborted();let d=await e.definition.run({signal:c});c.throwIfAborted();let m=qd.parse(d);for(let p of m.alerts??[])c.throwIfAborted(),await this.recordAlert(n,p,{deliver:u,includeInInbox:p.includeInInbox??e.definition.includeInInbox!==!1});c.throwIfAborted(),await this.state.set(this.lastSuccessKey(n),{kind:"last-success",checkId:n,at:this.currentTime().toISOString()})},a=se.tryPromise({try:(l)=>(o=i(l),o),catch:(l)=>l}),s=await se.runPromiseExit(a,{signal:t});if(o)await Promise.allSettled([o]);if(ot.isSuccess(s))return!0;if(t.aborted)throw t.reason;throw Pr.squash(s.cause)}getRegisteredCheckIds(){return[...this.checks.keys()]}trackCatchUp(e){let t=this.enqueueCatchUpIfNeeded(e.definition);e.catchUpTasks.add(t);let n=()=>{e.catchUpTasks.delete(t)};return t.then(n,n),t}releaseRegisteredCheck(e,t){if(e.releasePromise)return e.releasePromise;let n=e.definition.id;if(this.checks.get(n)===e)this.checks.delete(n);let o=this.releaseRegisteredCheckOnce(e,t);return e.releasePromise=o,o}async releaseRegisteredCheckOnce(e,t){try{await this.settleRegisteredCheck(e,t)}finally{let n=this.pluginChecks.get(e.pluginId);if(n?.delete(e),n?.size===0)this.pluginChecks.delete(e.pluginId)}}async settleRegisteredCheck(e,t){let n=[];if(e.scheduledJob){let o=e.scheduledJob;delete e.scheduledJob;try{n.push(o.stop())}catch(i){n.push(Promise.reject(i))}}if(e.activeCheck)e.activeCheck.controller.abort(t),n.push(e.activeCheck.settled);n.push(...e.catchUpTasks),await this.drainCleanupTasks(n)}async drainCleanupTasks(e){let t=await Promise.allSettled(e),n=[];for(let o of t)if(o.status==="rejected")n.push(o.reason);if(n.length===1)throw n[0];if(n.length>1)throw AggregateError(n,"Recurring check cleanup failed")}schedule(e){let t=e.definition,n=Ld(this.brainId,t.id,t.cadence);e.scheduledJob=this.scheduler.scheduleCron(n.expression,async()=>{try{await this.enqueue(t.id)}catch(o){this.logger.error(`Failed to enqueue scheduled recurring check ${t.id}`,o)}},{timezone:"UTC"})}async enqueueCatchUpIfNeeded(e){let t=this.currentTime(),n=Ld(this.brainId,e.id,e.cadence),o=Kx(t,n),i=await this.state.get(this.lastSuccessKey(e.id));if(i?.kind==="last-success"&&new Date(i.at)>=o)return;await this.enqueue(e.id)}enqueue(e){let t={source:"shell",metadata:{operationType:"data_processing",operationTarget:e,silent:!0},maxRetries:3,deduplication:"skip",deduplicationKey:e};return this.jobQueue.enqueue({type:Is,data:{checkId:e},options:t})}async listOpenAlerts(){return(await this.state.list({keyPrefix:"alert:"})).flatMap((t)=>{let n=t.value;if(n.kind!=="alert"||n.status==="resolved")return[];if(!(n.includeInInbox??this.checks.get(n.checkId)?.definition.includeInInbox!==!1))return[];return[{id:t.key,checkId:n.checkId,title:n.alert.title,body:n.alert.body,observedAt:n.observedAt}]}).sort((t,n)=>t.observedAt.localeCompare(n.observedAt)||t.id.localeCompare(n.id))}async resolveOpenAlert(e){await this.alertOperations.run(e,async()=>{let t=await this.state.get(e),n=t?.kind==="alert"&&(t.includeInInbox??this.checks.get(t.checkId)?.definition.includeInInbox!==!1);if(t?.kind!=="alert"||t.status==="resolved"||!n)throw Error("Recurring-check inbox item is not open");await this.state.set(e,{...t,status:"resolved",resolvedAt:this.currentTime().toISOString()})})}async flushPendingAlerts(e){let t=await this.state.list({keyPrefix:this.alertKeyPrefix(e)});for(let n of t)await this.alertOperations.run(n.key,async()=>{let o=await this.state.get(n.key);if(o?.kind==="alert"&&(o.status==="pending"||o.status==="suppressed"))await this.deliverStoredAlert(n.key,o)})}async suppressPendingAlerts(e){let t=await this.state.list({keyPrefix:this.alertKeyPrefix(e)});for(let n of t)await this.alertOperations.run(n.key,async()=>{let o=await this.state.get(n.key);if(o?.kind==="alert"&&o.status==="pending")await this.state.set(n.key,{...o,status:"suppressed"})})}async recordAlert(e,t,n){let o=Yi.parse(t),i=this.alertKey(e,o.dedupeKey);await this.alertOperations.run(i,async()=>{let a=await this.state.get(i);if(a?.kind==="alert"){let l=a.includeInInbox===n.includeInInbox?a:{...a,includeInInbox:n.includeInInbox};if(l!==a)await this.state.set(i,l);if(l.status==="delivered"||l.status==="resolved")return;if(n.deliver)await this.deliverStoredAlert(i,l);return}let s={kind:"alert",checkId:e,dedupeKey:o.dedupeKey,status:n.deliver?"pending":"suppressed",alert:o,observedAt:this.currentTime().toISOString(),includeInInbox:n.includeInInbox};if(await this.state.set(i,s),n.deliver)await this.deliverStoredAlert(i,s)})}async deliverStoredAlert(e,t){if(await this.delivery.deliver(t.alert)===!1)return;await this.state.set(e,{...t,status:"delivered",deliveredAt:this.currentTime().toISOString()})}currentTime(){return this.clock?new Date(this.clock.currentTimeMillisUnsafe()):this.nowFallback()}lastSuccessKey(e){return`run:${yn(e)}`}alertKeyPrefix(e){return`alert:${yn(e)}:`}alertKey(e,t){return`${this.alertKeyPrefix(e)}${yn(t)}`}}function Ld(e,t,n){let o=n==="daily"?$d:ZB,i=o/60000,a=yn(`${e}\x00${t}\x00${n}`),s=Number.parseInt(a.slice(0,12),16)%i,l=s%60,c=Math.floor(s/60),u=c%24;return{expression:n==="daily"?`${l} ${u} * * *`:`${l} ${u} * * ${Math.floor(c/24)}`,offsetMs:s*60000,periodMs:o,anchorMs:n==="daily"?0:KB}}function Kx(e,t){let n=e.getTime(),o=n-t.anchorMs,a=t.anchorMs+Math.floor(o/t.periodMs)*t.periodMs+t.offsetMs;if(a>n)a-=t.periodMs;return new Date(a)}function Vx(e,t){if(!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(e))throw Error(`Invalid recurring-check ${t}: ${e}. Use 1-64 alphanumeric, _, or - characters.`)}var $e=Qx("runtime_state_records",{namespace:ks("namespace").notNull(),key:ks("key").notNull(),value:ks("value",{mode:"json"}).notNull(),createdAt:Fd("created_at").notNull(),updatedAt:Fd("updated_at").notNull()},(e)=>({pk:Xx({columns:[e.namespace,e.key]}),namespaceUpdatedAtIdx:Yx("idx_runtime_state_namespace_updated_at").on(e.namespace,e.updatedAt)}));function tT(e){return eT({url:e.url,schema:{runtimeStateRecords:$e},authToken:e.authToken,authTokenEnv:"RUNTIME_STATE_DATABASE_AUTH_TOKEN"})}var XB=/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/,aT=512;class Gd{db;namespace;schema;now;constructor(e,t,n,o=()=>new Date){eG(t),this.db=e,this.namespace=t,this.schema=n,this.now=o}async get(e){let t=Bn(e),o=(await this.db.select().from($e).where(Gn(nr($e.namespace,this.namespace),nr($e.key,t))).limit(1))[0];if(!o)return null;return this.schema.parse(o.value)}async has(e){let t=Bn(e);return(await this.db.select({key:$e.key}).from($e).where(Gn(nr($e.namespace,this.namespace),nr($e.key,t))).limit(1)).length>0}async set(e,t){let n=Bn(e),o=this.schema.parse(t),i=this.now().getTime();await this.db.insert($e).values({namespace:this.namespace,key:n,value:o,createdAt:i,updatedAt:i}).onConflictDoUpdate({target:[$e.namespace,$e.key],set:{value:o,updatedAt:i}})}async setIfNotExists(e,t){let n=Bn(e),o=this.schema.parse(t),i=this.now().getTime(),a=await this.db.insert($e).values({namespace:this.namespace,key:n,value:o,createdAt:i,updatedAt:i}).onConflictDoNothing({target:[$e.namespace,$e.key]});return Number(a.rowsAffected)>0}async compareAndSet(e,t,n){let o=Bn(e),i=this.schema.parse(t),a=this.schema.parse(n),s=await this.db.update($e).set({value:a,updatedAt:this.now().getTime()}).where(Gn(nr($e.namespace,this.namespace),nr($e.key,o),nr($e.value,i)));return Number(s.rowsAffected)===1}async delete(e){let t=Bn(e),n=await this.db.delete($e).where(Gn(nr($e.namespace,this.namespace),nr($e.key,t)));return Number(n.rowsAffected)>0}async list(e={}){return(await this.listRows(e)).map((n)=>({key:n.key,value:this.schema.parse(n.value),createdAt:new Date(n.createdAt),updatedAt:new Date(n.updatedAt)}))}async clear(e={}){let t=await this.db.delete($e).where(Gn(nr($e.namespace,this.namespace),rT(e.keyPrefix)));return Number(t.rowsAffected)}async listRows(e){let{keyPrefix:t,afterKey:n,limit:o}=e;if(n!==void 0)Bn(n);if(o!==void 0)r.number().int().min(1).max(1000).parse(o);let i=this.db.select({...nT($e),key:Bd`CAST(${$e.key} AS BLOB)`.mapWith((a)=>new TextDecoder("utf-8",{fatal:!0}).decode(a))}).from($e).where(Gn(nr($e.namespace,this.namespace),rT(t),n!==void 0?oT($e.key,n):void 0)).orderBy(iT($e.key)).$dynamic();return o===void 0?i:i.limit(o)}}function eG(e){if(!XB.test(e))throw Error(`Invalid runtime state namespace: ${e}. Use 1-128 alphanumeric, _, ., :, or - characters.`)}function Bn(e){if(e.length===0||e.length>aT)throw Error("Runtime state keys must be 1-512 characters long");return e}function rT(e){if(e===void 0)return;return tG(e),Bd`substr(CAST(${$e.key} AS BLOB), 1, length(CAST(${e} AS BLOB))) = CAST(${e} AS BLOB)`}function tG(e){if(e.length>aT)throw Error("Runtime state key prefixes must be 512 characters or shorter");return e}class Rs{db;client;logger;databaseUrl;walInitialization=null;walInitializationSettled=!1;closeRequested=!1;clientClosed=!1;static createFresh(e,t){return new Rs(e,t??fr.getInstance())}constructor(e,t){let{db:n,client:o,url:i}=tT(e);this.db=n,this.client=o,this.databaseUrl=i,this.logger=t.child("RuntimeStateService")}initialize(){if(this.closeRequested)return Promise.resolve();return this.walInitialization??=this.initializeWALMode(),this.walInitialization}async initializeWALMode(){try{await sT(this.client,this.databaseUrl)}catch(e){this.logger.warn("Failed to enable runtime state WAL mode (non-fatal)",e)}finally{if(this.walInitializationSettled=!0,this.closeRequested)this.closeClient()}}scoped(e){return new Gd(this.db,e.namespace,e.schema)}close(){if(this.closeRequested=!0,!this.walInitialization||this.walInitializationSettled)this.closeClient()}closeClient(){if(this.clientClosed)return;this.clientClosed=!0,this.client.close()}}var Jd=et.Service("@brains/runtime-state/RuntimeStateService");function lT(e){return hn(Jd,()=>{let t=e.service??Rs.createFresh(e.config,e.logger);return{service:t,close:()=>t.close()}})}async function Wd(e,t){if(e.status==="running"){t.warn(`Daemon already running: ${e.name}`);return}e.status="starting",delete e.error;try{await e.daemon.start(),e.status="running",e.startedAt=new Date,t.debug(`Daemon started successfully: ${e.name}`)}catch(n){throw e.status="error",e.error=Xi(n),t.warn(`Daemon ${e.name} failed to start: ${Ce(n)}`),n}}async function Hd(e,t){if(e.status==="stopped"){t.warn(`Daemon already stopped: ${e.name}`);return}e.status="stopping";try{await e.daemon.stop(),e.status="stopped",e.stoppedAt=new Date,t.debug(`Daemon stopped successfully: ${e.name}`)}catch(n){throw e.status="error",e.error=Xi(n),t.error(`Failed to stop daemon: ${e.name}`,n),n}}async function cT(e){if(!e.daemon.healthCheck)return;try{let t=await e.daemon.healthCheck();return e.health=t,t}catch(t){let n={status:"error",message:Ce(t),lastCheck:new Date};return e.health=n,n}}function uT(e){return{name:e.name,pluginId:e.pluginId,status:e.status,health:e.health}}class Es{daemons=new Map;daemonScopes=new Map;daemonTransitions=new Map;logger;static createFresh(e){return new Es(e)}constructor(e){this.logger=e.child("DaemonRegistry")}register(e,t,n){if(this.daemonScopes.has(e))throw Error(`Cannot overwrite running daemon: ${e}`);if((this.daemonTransitions.get(e)?.pending??0)>0)throw Error(`Cannot overwrite transitioning daemon: ${e}`);if(this.daemons.has(e))this.logger.warn(`Daemon already registered: ${e}, overwriting`);let o={name:e,daemon:t,pluginId:n,status:"stopped"};this.daemons.set(e,o),this.logger.debug(`Registered daemon: ${e} from plugin: ${n}`)}has(e){return this.daemons.has(e)}get(e){return this.daemons.get(e)}start(e){if(!this.daemons.has(e))return Promise.reject(Error(`Daemon not registered: ${e}`));return this.enqueueTransition(e,"start",()=>this.startDaemon(e))}async startDaemon(e){let t=this.requireDaemon(e);if(this.daemonScopes.has(e)){await Wd(t,this.logger);return}let n=se.runSync(Xe.make()),o=se.acquireRelease(se.promise(()=>Wd(t,this.logger)),()=>se.promise(()=>Hd(t,this.logger)));try{await se.runPromise(Xe.provide(o,n)),this.daemonScopes.set(e,n)}catch(i){throw await se.runPromise(Xe.close(n,ot.fail(i))),i}}stop(e){if(!this.daemons.has(e))return Promise.reject(Error(`Daemon not registered: ${e}`));return this.enqueueTransition(e,"stop",()=>this.stopDaemon(e))}async stopDaemon(e){let t=this.requireDaemon(e),n=this.daemonScopes.get(e);if(!n){await Hd(t,this.logger);return}this.daemonScopes.delete(e),await se.runPromise(Xe.close(n,ot.void))}async checkHealth(e){let t=this.daemons.get(e);if(!t)throw Error(`Daemon not registered: ${e}`);return cT(t)}getByPlugin(e){return Array.from(this.daemons.values()).filter((t)=>t.pluginId===e)}getAll(){return Array.from(this.daemons.keys())}getAllInfo(){return Array.from(this.daemons.values())}async getStatuses(){let e=this.getAllInfo();for(let t of e)if(t.daemon.healthCheck)await this.checkHealth(t.name);return e.map(uT)}unregister(e){if(!this.daemons.has(e))return this.logger.warn(`Daemon not registered: ${e}`),Promise.resolve();return this.enqueueTransition(e,"unregister",async()=>{let t=this.requireDaemon(e);if(this.daemonScopes.has(e)||t.status!=="stopped")await this.stopDaemon(e);this.daemons.delete(e),this.logger.debug(`Unregistered daemon: ${e}`)},!0)}abandon(e){let t=this.daemons.get(e);if(!t)return;if(t.status!=="stopped"||this.daemonScopes.has(e)||(this.daemonTransitions.get(e)?.pending??0)>0)throw Error(`Cannot abandon active daemon: ${e}`);this.daemons.delete(e),this.logger.debug(`Abandoned daemon registration: ${e}`)}async startPlugin(e){let t=this.getByPlugin(e);this.logger.debug(`Starting ${t.length} daemons for plugin: ${e}`);let n,o=[];for(let i of t){let a=this.daemonScopes.has(i.name);try{if(await this.start(i.name),!a)o.push(i.name)}catch(s){if(n??=Xi(s),!a)o.push(i.name)}}if(n){for(let i of o.reverse())try{await this.stop(i)}catch(a){this.logger.error(`Failed to roll back daemon: ${i}`,a)}throw n}}async stopPlugin(e){let t=this.getByPlugin(e);this.logger.debug(`Stopping ${t.length} daemons for plugin: ${e}`);for(let n of t)try{await this.stop(n.name)}catch(o){this.logger.error(`Failed to stop daemon: ${n.name}`,o)}}async clear(){this.logger.debug("Clearing all daemons");for(let e of[...this.daemons.keys()])try{await this.unregister(e)}catch(t){this.logger.error(`Failed to unregister daemon during clear: ${e}`,t)}this.logger.debug("All daemons cleared")}requireDaemon(e){let t=this.daemons.get(e);if(!t)throw Error(`Daemon not registered: ${e}`);return t}enqueueTransition(e,t,n,o=!1){let i=this.daemonTransitions.get(e);if(!i)i={tail:Promise.resolve(),lastKind:void 0,lastPromise:void 0,pending:0,terminal:!1},this.daemonTransitions.set(e,i);if(t==="start"&&i.terminal)return Promise.reject(Error(`Daemon is being unregistered: ${e}`));if(i.lastKind===t&&i.lastPromise)return i.lastPromise;if(o)i.terminal=!0;i.pending++;let a=i.tail.then(n),s=()=>{if(i.pending--,i.pending===0)this.daemonTransitions.delete(e)},l=a.then(s,s);return i.tail=l,i.lastKind=t,i.lastPromise=a,a}}var rG=r.object({projectionId:r.string().min(1),reason:r.string().min(1),openedAt:r.number().int().nonnegative(),expiresAt:r.number().int().nonnegative()}),nG=8,oG=32,iG=128,aG=5,sG=600000,lG=600000,cG=1000,uG="shell.projection-circuits";class As{operationContext;options;circuitStore;roots=new Map;reservedJobs=new Map;circuits=new Map;projections;static createFresh(e,t={}){return new As(e,t)}constructor(e,t){this.operationContext=e,this.options={maxDerivationDepth:t.maxDerivationDepth??nG,maxJobsPerRoot:t.maxJobsPerRoot??oG,maxMutationsPerRoot:t.maxMutationsPerRoot??iG,repeatedTargetLimit:t.repeatedTargetLimit??aG,retentionMs:t.retentionMs??sG,circuitOpenMs:t.circuitOpenMs??lG,maxTrackedRoots:t.maxTrackedRoots??cG,now:t.now??Date.now};for(let[n,o]of Object.entries(this.options)){if(n==="now")continue;if(typeof o!=="number"||!Number.isInteger(o)||o<=0)throw Error(`${n} must be a positive integer`)}this.circuitStore=t.runtimeState?.scoped({namespace:uG,schema:rG})}async initialize(e){if(this.projections)throw Error("Projection runtime supervisor is already initialized");if(this.projections=new Map(e.projections.map((n)=>[n.id,n])),!this.circuitStore)return;let t=this.options.now();for(let n of await this.circuitStore.list()){let o=n.value;if(o.expiresAt<=t||!this.projections.has(o.projectionId)){await this.circuitStore.delete(n.key);continue}this.circuits.set(o.projectionId,o)}}async reserveJobAdmission(e){let t=e.projectionId;if(!t)return this.createNoopJobReservation();let n=this.options.now();if(await this.prune(n),await this.requireProjection(t,n),await this.assertCircuitClosed(t,n),await this.assertDepth(e,n),e.projectionLineage.filter((u)=>u===t).length>1)await this.rejectAndOpen(t,`Projection ${t} repeats in one causal lineage`,n);let i=e.rootJobId,a=this.roots.get(i)?.jobs??0,s=this.reservedJobs.get(i)??0;if(a+s+1>this.options.maxJobsPerRoot)await this.rejectAndOpen(t,`Root ${i} exceeded projection job budget ${this.options.maxJobsPerRoot}`,n);this.reservedJobs.set(i,s+1);let l=!1,c=(u)=>{if(l)return;if(l=!0,this.releaseJobReservation(i),!u)return;let d=this.options.now(),m=this.getRootCounters(i,d);m.jobs++,m.updatedAt=d};return{commit:()=>c(!0),rollback:()=>c(!1)}}async assertMutationAdmission(e){let t=this.operationContext.current()?.provenance,n=t?.projectionId;if(!t||!n)return;let o=this.options.now();await this.prune(o),await this.requireProjection(n,o),await this.assertCircuitClosed(n,o);let i=this.getRootCounters(t.rootJobId,o);if(i.mutations++,i.updatedAt=o,i.mutations>this.options.maxMutationsPerRoot)await this.rejectAndOpen(n,`Root ${t.rootJobId} exceeded projection mutation budget ${this.options.maxMutationsPerRoot}`,o);let a=`${n}\x00${e.entityType}\x00${e.entityId}`,s=(i.targetMutations.get(a)??0)+1;if(i.targetMutations.set(a,s),s>this.options.repeatedTargetLimit)await this.rejectAndOpen(n,`Projection ${n} repeatedly mutated ${e.entityType}:${e.entityId}`,o)}async getDiagnostics(){let e=this.options.now();await this.prune(e);let t=Array.from(this.circuits.values()).sort((n,o)=>n.projectionId.localeCompare(o.projectionId)).map((n)=>({...n}));return{status:t.length>0?"unhealthy":"healthy",initialized:this.projections!==void 0,trackedRoots:this.roots.size,openCircuits:t}}async requireProjection(e,t){if(!this.projections)throw Error("Projection runtime supervisor is not initialized");let n=this.projections.get(e);if(!n)throw await this.rejectAndOpen(e,`Projection ${e} is not declared in the validated graph`,t),Error(`Projection ${e} is not declared`);return n}async assertDepth(e,t){let n=e.projectionId;if(!n)return;if(e.derivationDepth>this.options.maxDerivationDepth)await this.rejectAndOpen(n,`Projection ${n} depth ${e.derivationDepth} exceeds global maximum ${this.options.maxDerivationDepth}`,t)}async assertCircuitClosed(e,t){let n=this.circuits.get(e);if(!n)return;if(n.expiresAt<=t){this.circuits.delete(e),await this.circuitStore?.delete(e);return}throw Error(`Projection circuit ${e} is open: ${n.reason}`)}async rejectAndOpen(e,t,n){let o={projectionId:e,reason:t,openedAt:n,expiresAt:n+this.options.circuitOpenMs};this.circuits.set(e,o);try{await this.circuitStore?.set(e,o)}catch(i){throw Error(`Projection ${e} was rejected but its circuit could not be persisted`,{cause:i})}throw Error(t)}createNoopJobReservation(){return{commit:()=>{},rollback:()=>{}}}releaseJobReservation(e){let t=this.reservedJobs.get(e);if(t===void 0||t<=1){this.reservedJobs.delete(e);return}this.reservedJobs.set(e,t-1)}getRootCounters(e,t){let n=this.roots.get(e);if(n)return n;if(this.roots.size>=this.options.maxTrackedRoots){let i=Array.from(this.roots.entries()).sort(([a,s],[l,c])=>s.updatedAt-c.updatedAt||a.localeCompare(l))[0];if(i)this.roots.delete(i[0])}let o={jobs:0,mutations:0,targetMutations:new Map,updatedAt:t};return this.roots.set(e,o),o}async prune(e){for(let[t,n]of this.roots)if(e-n.updatedAt>=this.options.retentionMs)this.roots.delete(t);for(let[t,n]of this.circuits)if(n.expiresAt<=e)this.circuits.delete(t),await this.circuitStore?.delete(t)}}var dG={web:{serves:!0,executes:!1,handlerRegistrationMode:"validation-only",progressMonitorMode:"durable-reader",projectionActivation:"scheduler"},worker:{serves:!1,executes:!0,handlerRegistrationMode:"execution-only",progressMonitorMode:"durable-writer",projectionActivation:"executor"},combined:{serves:!0,executes:!0,handlerRegistrationMode:"combined",progressMonitorMode:"combined",projectionActivation:"scheduler"}};function Ps(e){return dG[e??"combined"]}var pG=20,mG=0.5,gG=0.06,fG=5;function Ms(e,t){let n=e[t];return typeof n==="string"&&n.trim().length>0?n.trim():void 0}function dT(e){return typeof e==="string"&&e.startsWith("https://")?e:void 0}function hG(e){if(typeof e!=="object"||e===null)return;let t=new Map(Object.entries(e)),n=t.get("name");if(typeof n!=="string"||!n)return;let o=dT(t.get("url"));return{name:n,...o?{url:o}:{}}}function yG({entity:e},t){let n=Ms(e.metadata,"pageTitle")??Ms(e.metadata,"title")??Ms(e.metadata,"name"),o=Ms(e.metadata,"slug")??e.id,i=t.siteBaseUrl?.replace(/^https?:\/\//,"").replace(/\/+$/,""),a=dT(e.metadata.origin),s=hG(e.metadata.brain),l=a??(i?new URL(t.urlFor(e.entityType,o),`https://${i}`).href:void 0);return{id:`${e.entityType}:${e.id}`,...n?{title:n}:{},source:e.entityType,entityType:e.entityType,entityId:e.id,...l?{url:l}:{},...s?{brain:s}:{}}}function pT(e){return async({answer:t})=>{let o=(await e.entityService.search({query:t,options:{limit:pG,minScore:mG,visibilityScope:Wt("public"),publishedOnly:!0}})).filter((a)=>e.isCitable(a.entity.entityType)),i=Math.max(...o.map((a)=>a.score));return o.filter((a)=>a.score>=i-gG).slice(0,fG).map((a)=>yG(a,e))}}function vG(e,t,n,o,i){return[js.created,js.updated,js.deleted].map((s)=>e.subscribe(s,async(l)=>{if(l.payload.entityType===t&&(n===null||l.payload.entityId===n)){await o();let c=s.replace("entity:","");i.debug(`${t} entity ${c}, cache refreshed`)}return{success:!0}}))}function mT(e,t,n,o){return vG(e,t,t,async()=>{await n(),await e.send({type:Yr.identityChanged,payload:{entityType:t},sender:"shell",broadcast:!0})},o)}async function bG(e,t,n){let o=_G(e.kind);if(!o)return null;try{let i=t.scoped({namespace:o,refKind:e.kind,routePath:""});return SG(await i.read(e.id),e)}catch(i){return n.debug("Skipped unavailable prior runtime upload",{uploadKind:e.kind,uploadId:e.id,error:Ce(i)}),null}}function _G(e){return e==="upload"?"upload":null}function SG(e,t){let{record:n,content:o}=e;if(wG(n.mediaType))return{kind:"text",filename:n.filename,mediaType:n.mediaType,content:new TextDecoder("utf-8").decode(o).replace(/^\uFEFF/,""),sizeBytes:n.sizeBytes,source:t};return{kind:"file",filename:n.filename,mediaType:n.mediaType,data:new Uint8Array(o),sizeBytes:n.sizeBytes,source:t}}function wG(e){let t=e.toLowerCase();return t.startsWith("text/")||t==="application/json"}function ST(e){let{config:t,entityService:n,logger:o,messageBus:i,aiService:a,mcpService:s,conversationService:l,runtimeUploadRegistry:c,disposables:u,executionOnly:d=!1}=e,m=vT.createFresh(n,o,t.identity);u.push(...mT(i,Zt.BRAIN_CHARACTER,()=>m.refreshCache(),o));let p=bT.createFresh(n,o,t.profile),f=_T.createFresh(o,async(_)=>{let y=await Ts(i,"shell:canonical-identity-service",_).catch(()=>null);if(!y?.canonicalId)return null;return{userId:y.userId,canonicalId:y.canonicalId,displayName:y.displayName}}),g=Dd({guestPricing:a.getConfig().model==="gpt-5.6-luna"?cd:void 0,model:a.getModel(),modelId:a.getConfig().model,webSearch:a.getConfig().webSearch,temperature:a.getConfig().temperature,maxTokens:a.getConfig().maxTokens,reasoningEffort:a.getConfig().reasoningEffort,messageBus:i}),h=Id(t.name),v=new fa(t.entityDisplay),x=Qi.createFresh(s,l,m,p,o,{agentFactory:g,canonicalIdentityResolver:f,...e.embeddingUsage?{embeddingUsage:e.embeddingUsage}:{},...t.embedding.enabled?{indexReadiness:n,guestAnswerSources:pT({entityService:n,isCitable:(_)=>v.isCitable(_),urlFor:(_,y)=>v.generateUrl(_,y),siteBaseUrl:t.siteBaseUrl})}:{},uploadAttachmentResolver:(_)=>bG(_,c,o),guestAskedBefore:async(_)=>{let y=await i.collect({type:gT,sender:"shell:agent-service",payload:_});return fT(y.flatMap((w)=>("noop"in w)||!w.success?[]:[w.data]))},agentContextProvider:async(_)=>(await i.collect({type:hT,sender:"shell:agent-service",payload:_})).flatMap((w)=>{if("noop"in w||!w.success)return[];return yT(w.data)}),...h?{assistantAgentId:h}:{},...t.agentInstructions&&{agentInstructions:t.agentInstructions}});if(u.push(...mT(i,Zt.ANCHOR_PROFILE,()=>p.refreshCache(),o)),!d)u.push(i.subscribe(Yr.identityChanged,async()=>(x.invalidateAgent(),{success:!0})));return{identityService:m,profileService:p,canonicalIdentityService:f,agentService:x}}var ea=et.Service("@brains/job-queue/JobQueueService"),Os=et.Service("@brains/job-queue/BatchJobManager"),Ns=et.Service("@brains/job-queue/JobProgressMonitor"),Ds=et.Service("@brains/job-queue/JobQueueWorker");function CT(e){return hn(ea,()=>{let t=e.service??wT.createFresh(e.config,e.logger,{...e.operationContext&&{operationContext:e.operationContext},...e.projectionAdmission&&{projectionAdmission:e.projectionAdmission},...e.handlerRegistrationMode&&{handlerRegistrationMode:e.handlerRegistrationMode}});return{service:t,close:()=>t.close()}})}function kT(e){let t=!1,n=se.gen(function*(){let o=yield*ea,i=e.batchJobManager??TT.createFresh(o,e.logger),a=e.jobProgressMonitor??IT.createFresh(o,e.messageBus,i,e.logger,e.progressMonitorMode),s=e.jobQueueWorker??xT.createFresh(o,a,e.logger,{pollInterval:100,concurrency:e.workerConcurrency,autoStart:!1,...e.onWorkerUnhealthy&&{onUnhealthy:e.onWorkerUnhealthy}},{...e.operationContext&&{operationContext:e.operationContext},...e.projectionBatchScope&&{projectionBatchScope:e.projectionBatchScope}});return et.make(Os,i).pipe(et.add(Ns,a),et.add(Ds,s))});return{layer:Xr.effectContext(se.acquireRelease(n,(o)=>t?se.void:xG(o))),abandon:()=>{t=!0}}}function xG(e){let t=et.get(e,Ds),n=et.get(e,Ns),o=et.get(e,Os);return se.gen(function*(){let i=yield*se.exit(se.tryPromise({try:()=>t.stop(),catch:(c)=>c})),a=yield*se.exit(se.tryPromise({try:()=>n.stop(),catch:(c)=>c})),s=yield*se.exit(se.tryPromise({try:async()=>{await o.stop()},catch:(c)=>c})),l=[i,a,s].find(ot.isFailure);if(l)yield*se.die(Pr.squash(l.cause))})}function TG(e,t=(n)=>process.exit(n)){return(n)=>{e.error("Job queue worker requires process restart",{reason:n,exitCode:1}),t(1)}}function zs(e){let t=se.runSyncExit(Xe.close(e,ot.void));if(ot.isFailure(t))throw Pr.squash(t.cause)}function RT(e){let t=e.operationContext??Us.createFresh(),n=se.runSync(Xe.make()),o,i;try{let a=se.runSync(Xr.buildWithScope(CT({config:e.jobQueueConfig,logger:e.logger,operationContext:t,...e.projectionAdmission&&{projectionAdmission:e.projectionAdmission},...e.handlerRegistrationMode&&{handlerRegistrationMode:e.handlerRegistrationMode},...e.dependencies?.jobQueueService&&{service:e.dependencies.jobQueueService}}),n)),s=et.get(a,ea),l=se.runSync(Xe.make());o=l;let c=kT({messageBus:e.messageBus,logger:e.logger,operationContext:t,...e.projectionBatchScope&&{projectionBatchScope:e.projectionBatchScope},onWorkerUnhealthy:TG(e.logger),workerConcurrency:e.workerConcurrency,...e.progressMonitorMode&&{progressMonitorMode:e.progressMonitorMode},...e.dependencies?.batchJobManager&&{batchJobManager:e.dependencies.batchJobManager},...e.dependencies?.jobProgressMonitor&&{jobProgressMonitor:e.dependencies.jobProgressMonitor},...e.dependencies?.jobQueueWorker&&{jobQueueWorker:e.dependencies.jobQueueWorker}});i=c;let u=se.runSync(Xr.buildWithScope(c.layer.pipe(Xr.provide(Xr.succeed(ea,s))),l)),d=et.get(u,Os),m=et.get(u,Ns),p=et.get(u,Ds),f,g=!1,h=!1;return{batchJobManager:d,jobProgressMonitor:m,jobQueueService:s,jobQueueWorker:p,closeRuntime:()=>(g=!0,f??=se.runPromise(Xe.close(l,ot.void)),f),rollbackRuntime:()=>{if(g)return;g=!0,c.abandon(),zs(l)},closeDatabase:()=>{if(h)return;h=!0,zs(n)}}}catch(a){if(o)try{i?.abandon(),zs(o)}catch(s){e.logger.warn("Failed to release partial job runtime acquisition",s)}try{zs(n)}catch(s){e.logger.warn("Failed to release partial job database acquisition",s)}throw a}}function AT(e){return{deliver:async(t)=>{if(!e.hasHandlers(Vd))return!1;let n=await e.send({type:Vd,payload:{title:t.title,body:t.body,...t.html?{html:t.html}:{}},sender:"shell.recurring-checks"});if(!("success"in n)||!n.success||!n.data)throw Error("Recurring alert delivery failed");let o=ET.safeParse(n.data);if(!o.success||o.data.status!=="sent")throw Error("Recurring alert delivery failed");return!0}}}function MT(e){return{sourceId:"recurring-checks",displayName:"Recurring checks",list:async()=>(await e.listOpenAlerts()).map((t)=>({id:t.id,title:PT(t.title,160),summary:PT(t.body,1000),receivedAt:t.observedAt,urgency:"high",actions:[{id:"resolve",label:"Dismiss",confirm:!0}]})),act:async(t,n,o)=>{if(o.permissionLevel!=="admin")throw Error("Admin permission required");if(n!=="resolve")throw Error("Invalid recurring-check inbox action");await e.resolveOpenAlert(t)}}}function PT(e,t){return e.length<=t?e:e.slice(0,t)}function jT(e,t){if(t)return t;let n={debug:Ut.DEBUG,info:Ut.INFO,warn:Ut.WARN,error:Ut.ERROR}[e.logging.level];return fr.createFresh({level:n,context:e.logging.context,format:e.logging.format==="json"?"json":"text",...e.logging.file?{logFile:e.logging.file}:{}})}function OT(e){return{apiKey:e.ai.apiKey,model:e.ai.model,temperature:e.ai.temperature,maxTokens:e.ai.maxTokens,webSearch:e.ai.webSearch,...e.ai.reasoningEffort&&{reasoningEffort:e.ai.reasoningEffort},...e.ai.imageApiKey?{imageApiKey:e.ai.imageApiKey}:{}}}function No(e){return{url:e.url,...e.authToken?{authToken:e.authToken}:{}}}function eI(e){let{config:t,dependencies:n,initializerLogger:o,lifecycle:i,processRole:a}=e;o.debug("Initializing Shell services");let s=Ps(a),l=jT(t,n?.logger),c=n?.operationContext??Us.createFresh(),u=[],d=$i.createFresh(),m=n?.embeddingService??Li.createFresh({apiKey:t.ai.apiKey,logger:l,usage:d}),p=n?.aiService??Ui.createFresh(OT(t),l),f=n?.entityRegistry??DT.createFresh(l),g=n?.messageBus??QT.createFresh(l,c),h=n?.templateRegistry??UT.createFresh(l),v=n?.dataSourceRegistry??zT.createFresh(l),x=n?.renderService??qT.createFresh(h),_=n?.daemonRegistry??Es.createFresh(l),y=n?.pluginManager??XT.createFresh(l,_),w=n?.permissionService??new _s(t.permissions,{spaces:t.spaces,entityActionFloor:(me)=>f.getEntityTypeConfig(me).actionPolicy}),S=n?.profileKindRegistry??new YT(t.profileKind),C=n?.channelRegistry??new FT,I=n?.inboxRegistry??new BT,b=n?.inboxFollowUpRegistry??new GT(l),E=n?.operationalHealthRegistry??new KT,B=n?.accountSettingsRegistry??new $T,R=n?.attachmentRegistry??JT.createFresh(),U=n?.runtimeUploadRegistry??WT.createFresh({dataDir:t.dataDir,logger:l}),z=i.buildLayer(lT({config:No(t.runtimeStateDatabase),logger:l,...n?.runtimeStateService&&{service:n.runtimeStateService}})),N=et.get(z,Jd),re=n?.projectionRuntimeSupervisor??As.createFresh(c,{runtimeState:N}),Q=n?.mcpService??ZT.createFresh(g,l),V={},L={runFreshBatchScope:(me)=>V.current?V.current.runFreshBatchScope(me):me()},de=RT({dependencies:n,jobQueueConfig:No(t.jobQueueDatabase),workerConcurrency:t.jobQueue.workerConcurrency,messageBus:g,operationContext:c,projectionBatchScope:L,projectionAdmission:re,handlerRegistrationMode:s.handlerRegistrationMode,progressMonitorMode:s.progressMonitorMode,logger:l}),{batchJobManager:ee,jobProgressMonitor:k,jobQueueService:X,jobQueueWorker:W}=de;i.addSyncFinalizer(()=>de.closeDatabase()),i.addSyncFinalizer(()=>de.rollbackRuntime());let J=n?.recurringCheckService??new Cs({brainId:t.siteBaseUrl??t.dataDir,scheduler:new HT,runtimeState:N,clock:se.runSync(NT.Clock),jobQueue:X,logger:l,delivery:AT(g)});i.addSyncFinalizer(()=>J.abandon()),I.registerSource("shell.recurring-checks",MT(J)),i.addSyncFinalizer(()=>I.unregisterPlugin("shell.recurring-checks"));let K=(me,Y)=>{if(!s.serves)return;_.register(me,Y,"shell"),i.addSyncFinalizer(()=>_.abandon(me))};K("shell:recurring-checks",{start:()=>J.start(),stop:()=>J.stop()});let D=i.buildLayer(Hx({embeddingService:m,embeddingsEnabled:t.embedding.enabled,entityRegistry:f,logger:l,jobQueueService:X,messageBus:g,mutationAdmission:re,...n?.projectionRuntime?.now&&{projectionNow:n.projectionRuntime.now},dbConfig:No(t.database),embeddingDbConfig:No(t.embeddingDatabase),...n?.entityService&&{service:n.entityService}})),F=et.get(D,Ud);V.current=F.getProjectionStore();let G=i.buildLayer(Jx({dbConfig:No(t.conversationDatabase),logger:l,messageBus:g,...n?.conversationService&&{service:n.conversationService}})),Z=et.get(G,zd);K("shell:guest-retention",VT({intervalMs:60000,logger:l,run:async()=>{await Z.deleteExpiredGuestConversations(100)}})),i.addSyncFinalizer(()=>{for(let me of u.splice(0))try{me()}catch(Y){l.warn("Failed to dispose shell subscription",Y)}});let A=n?.contentService??new LT({logger:l,entityService:F,aiService:p,templateRegistry:h,dataSourceRegistry:v,generationAuthorizer:Bx(w,g)}),{identityService:O,profileService:H,canonicalIdentityService:P,agentService:q}=ST({config:t,entityService:F,embeddingService:m,embeddingUsage:d,entityRegistry:f,logger:l,messageBus:g,aiService:p,mcpService:Q,conversationService:Z,runtimeUploadRegistry:U,disposables:u,executionOnly:!s.serves});return{logger:l,operationContext:c,projectionRuntimeSupervisor:re,disposables:u,entityRegistry:f,messageBus:g,renderService:x,daemonRegistry:_,pluginManager:y,templateRegistry:h,dataSourceRegistry:v,mcpService:Q,embeddingService:m,entityService:F,aiService:p,conversationService:Z,contentService:A,jobQueueService:X,jobQueueWorker:W,batchJobManager:ee,jobProgressMonitor:k,jobServicesLifecycle:de,permissionService:w,identityService:O,profileService:H,canonicalIdentityService:P,profileKindRegistry:S,channelRegistry:C,inboxRegistry:I,inboxFollowUpRegistry:b,operationalHealthRegistry:E,accountSettingsRegistry:B,agentService:q,attachmentRegistry:R,runtimeUploadRegistry:U,runtimeStateService:N,recurringCheckService:J}}function iI(e,t){e.register(Zd.name,Zd),t.debug("Shell system templates registered")}function aI(e,t){e.register(Zo.BASE_ENTITY_DISPLAY,{name:"base-entity-display",description:"Display template for base entities",schema:Kd,formatter:new tI,requiredPermission:"public"}),t.debug("Base entity display template registered")}function sI(e,t){e.registerEntityType(Zt.NOTE,Kd,new rI,{projectionSourceRole:"primary"}),t.debug("Fallback base entity adapter registered")}function lI(e,t){let n=new nI;e.registerEntityType(Zt.BRAIN_CHARACTER,n.schema,n,{classification:"system",projectionSource:!1,projectionSourceRole:"excluded"}),t.debug("Brain character entity support registered")}function cI(e,t){let n=new oI;e.registerEntityType(Zt.ANCHOR_PROFILE,n.schema,n,{classification:"system",projectionSourceRole:"canonical"}),t.debug("Anchor profile entity support registered")}async function uI(e){let{plugins:t,pluginManager:n,logger:o,initOptions:i}=e,a=i?.registrationContext?.executionOnly,s=a?t.filter((l)=>l.type!=="interface"):t;o.debug(`Found ${s.length} plugins to register`);for(let l of s)o.debug(`Registering plugin: ${l.id}`),n.registerPlugin(l);if(await n.initializePlugins(i?.registrationContext),a)await n.registerInterfaceChannels(t.filter((l)=>l.type==="interface"),i.registrationContext);if(!i?.registerOnly){for(let{id:l,error:c}of n.getFailedPlugins())if(n.getPlugin(l)?.requiresDaemonStartup?.())throw c}o.debug("Plugin initialization complete")}class qs{logger;config;processRole;static createFresh(e,t,n){return new qs(e,t,n)}constructor(e,t,n){this.logger=e.child("ShellInitializer"),this.config=t,this.processRole=n}registerShellTemplates(e){iI(e,this.logger)}registerBaseEntityDisplayTemplate(e){aI(e,this.logger)}registerFallbackBaseEntity(e){sI(e,this.logger)}registerBrainCharacterSupport(e){lI(e,this.logger)}registerAnchorProfileSupport(e){cI(e,this.logger)}async initializePlugins(e,t){await uI({plugins:this.config.plugins,pluginManager:e,logger:this.logger,initOptions:t})}initializeServices(e,t){return eI({config:this.config,dependencies:t,initializerLogger:this.logger,lifecycle:e,...this.processRole&&{processRole:this.processRole}})}registerJobHandlers(e,t,n){let o=pI.createFresh(t,n);e.registerHandler(dI.contentGeneration,o,"shell")}wireShell(e,t){e.pluginManager.setShell(t)}async initializeAll(e,t,n,o){this.logger.debug("Starting Shell initialization");try{if(this.registerShellTemplates(e),this.registerBaseEntityDisplayTemplate(e),this.registerBrainCharacterSupport(t),this.registerAnchorProfileSupport(t),await this.initializePlugins(n,o),!t.hasEntityType(Zt.NOTE))this.registerFallbackBaseEntity(t);this.logger.debug("Shell registration phase complete")}catch(i){throw this.logger.error("Shell initialization failed",i),i}}}function mI(){let e,t;return{promise:new Promise((o,i)=>{e=o,t=i}),resolve:(o)=>e?.(o),reject:(o)=>t?.(o)}}async function Ls(e){let n=(await se.runPromise(se.all(e.map((o)=>se.result(se.tryPromise({try:o,catch:(i)=>i}))),{concurrency:"unbounded"}))).find(gI.isFailure);if(n)throw n.failure}var Qd=r.strictObject({waveId:r.string().trim().min(1),ruleId:r.string().trim().min(1)});class Yd{ruleById;store;coordinator;getJobStatus;onDiagnostic;inputContext;executionContext;reconcileTargets;now;constructor(e){let t=new Map;for(let n of e.rules){if(t.has(n.id))throw Error(`Duplicate executable projection rule "${n.id}"`);t.set(n.id,n)}this.ruleById=t,this.store=e.store,this.coordinator=e.coordinator,this.getJobStatus=e.getJobStatus??(async()=>null),this.onDiagnostic=e.onDiagnostic,this.inputContext=e.inputContext,this.executionContext=e.executionContext,this.reconcileTargets=e.reconcileTargets,this.now=e.now}validateAndParse(e){let t=Qd.safeParse(e);return t.success?t.data:null}async onTerminalError(e,t,n){let o=Qd.parse(t);await this.coordinator.failActiveWaveWithIncident({waveId:o.waveId,ruleId:o.ruleId,jobId:n,failureReason:"Projection rule job exhausted retries"})}async process(e,t,n,o){let i=Qd.parse(e),a=this.ruleById.get(i.ruleId);if(!a)throw Error(`Projection rule "${i.ruleId}" is not executable`);let[s,l,c,u]=await Promise.all([this.store.listWaveInputs(i.waveId),this.store.listWaveRules(i.waveId),this.store.getWave(i.waveId),this.getJobStatus(t)]);if(!c)throw Error(`Projection wave "${i.waveId}" does not exist`);if(c.status!=="running"&&c.status!=="superseded")throw Error(`Projection wave "${i.waveId}" is not active`);let d=l.find((S)=>S.ruleId===i.ruleId);if(!d)throw Error(`Projection rule "${i.ruleId}" is not scheduled for wave "${i.waveId}"`);let m={waveId:i.waveId,ruleId:a.id,ruleVersion:a.version,jobId:t,attemptNumber:(u?.retryCount??0)+1,cutoffGeneration:c.cutoffGeneration};if(await this.recordDiagnostic({...m,event:"attempt-started"}),c.status==="superseded"){let S=await this.store.listPendingInputs();return await this.recordDiagnostic({...m,event:"apply-completed",applyOutcome:"superseded",highestPendingGeneration:$s(S)}),{waveId:i.waveId,ruleId:a.id,outcome:"superseded",inputFingerprint:null,changedTargets:[]}}if(await this.store.supersedeWaveIfStale(i.waveId,this.now())){let S=await this.store.listPendingInputs();return await this.recordDiagnostic({...m,event:"apply-completed",applyOutcome:"superseded",highestPendingGeneration:$s(S)}),await this.coordinator.continueAfterSupersession(i.waveId),{waveId:i.waveId,ruleId:a.id,outcome:"superseded",inputFingerprint:null,changedTargets:[]}}let p=kG(s,l,d.level),f=await a.selectInput({waveId:i.waveId,inputs:p},this.inputContext,o),g=a.fingerprint(f),h={...m,inputFingerprint:g,selectedSourceCount:CG(f,p)};await this.recordDiagnostic({...h,event:"input-selected"});let v={ruleId:a.id,ruleVersion:a.version,inputFingerprint:g},x=await this.store.getRuleMemo(v);await this.recordDiagnostic({...h,event:"memo-resolved",memoHit:x!==null});let _;if(x)_=x.writeIntents;else{await this.recordDiagnostic({...h,event:"derive-started",memoHit:!1});try{_=await a.derive(f,this.executionContext,o),await this.recordDiagnostic({...h,event:"derive-completed",memoHit:!1})}catch(S){throw await this.recordDiagnostic({...h,event:o.aborted?"derive-cancelled":"derive-failed",memoHit:!1}),S}}let y=await this.store.applyRuleResult({waveId:i.waveId,ruleId:a.id,ruleVersion:a.version,inputFingerprint:g,writeIntents:_,completedAt:this.now()}),w=await this.store.listPendingInputs();if(!y)return await this.recordDiagnostic({...h,event:"apply-completed",memoHit:x!==null,applyOutcome:"superseded",highestPendingGeneration:$s(w)}),await this.coordinator.continueAfterSupersession(i.waveId),{waveId:i.waveId,ruleId:a.id,outcome:"superseded",inputFingerprint:g,changedTargets:[]};return await this.recordDiagnostic({...h,event:"apply-completed",memoHit:x!==null,applyOutcome:"applied",highestPendingGeneration:$s(w)}),await this.reconcileTargets(y.changedTargets),await this.coordinator.advanceActiveWave(i.waveId),{waveId:i.waveId,ruleId:a.id,outcome:"applied",inputFingerprint:g,changedTargets:y.changedTargets}}async recordDiagnostic(e){if(!this.onDiagnostic)return;try{await this.onDiagnostic(e)}catch(t){this.executionContext.logger.warn("Projection diagnostics callback failed",t)}}}function CG(e,t){if(typeof e==="object"&&e!==null&&"sources"in e&&Array.isArray(e.sources))return e.sources.length;return t.length}function $s(e){if(e.length===0)return null;return e.reduce((t,n)=>Math.max(t,n.generation),e[0]?.generation??0)}function kG(e,t,n){let o=e.map((a)=>({sourceType:a.sourceType,sourceId:a.sourceId,revision:a.revision,operation:a.operation,generation:a.generation})),i=t.filter((a)=>a.status==="completed"&&a.level<n).flatMap((a)=>a.changedTargets.map((s)=>({sourceType:s.entityType,sourceId:s.entityId,revision:s.contentHash??`deleted:${s.entityType}:${s.entityId}`,operation:s.operation})));return[...o,...i]}function RG(e){switch(e.jobStatus){case"failed":return"Projection rule job exhausted retries";case"completed":return"Projection rule job completed without applying its result";case"missing":return e.rule.jobId?"Projection rule job is missing":"Projection rule has no durable job id";default:return"Projection rule job is in an unexpected terminal state"}}var Do="shell:projection-rule";class Xd{store;queue;graph;ruleById;graphFingerprint;createWaveId;beforeWaveCompletion;scheduleWakeup;onScheduledWakeupError;now;operationQueue=new fI;scheduledWakeup;constructor(e){this.store=e.store,this.queue=e.queue,this.graph=e.graph,this.ruleById=PG(e.graph,e.rules),this.graphFingerprint=MG(e.graph,e.rules),this.createWaveId=e.createWaveId,this.beforeWaveCompletion=e.beforeWaveCompletion??(async()=>{}),this.scheduleWakeup=e.scheduleWakeup??EG,this.onScheduledWakeupError=e.onScheduledWakeupError??(()=>{}),this.now=e.now}dispose(){this.cancelScheduledWakeup()}advanceActiveWave(e){return this.runExclusive(async()=>{let t=await this.store.getActiveWave();if(t?.id!==e){let o=await this.store.getWave(e);if(o?.status==="completed")return o;throw Error(`Projection wave "${e}" is not active`)}let n=await this.advanceWave(t);if(n.status==="completed")await this.startNextWaveInternal();return n})}startNextWave(){return this.runExclusive(()=>this.startNextWaveInternal())}continueAfterSupersession(e){return this.runExclusive(async()=>{let t=await this.store.getActiveWave();if(t?.id===e)throw Error(`Projection wave "${e}" was not superseded`);if(t)return this.advanceWave(t);return this.startNextWaveInternal()})}failActiveWave(e){return this.runExclusive(async()=>{if((await this.store.getActiveWave())?.id!==e)throw Error(`Projection wave "${e}" is not active`);return this.store.failWave(e,this.now())})}failActiveWaveWithIncident(e){return this.runExclusive(async()=>{let t=await this.store.getActiveWave();if(t&&t.id!==e.waveId)throw Error(`Projection wave "${e.waveId}" is not active; "${t.id}" is running`);if(!t){let n=await this.store.getWave(e.waveId);if(n?.status==="superseded")return n}return this.store.failWaveWithIncident({...e,failedAt:this.now()})})}async startNextWaveInternal(){let e=await this.store.getActiveWave();if(e){let s=await this.advanceWave(e);if(s.status==="completed")await this.startNextWaveInternal();return s}let t=await this.store.listPendingInputs();if(t.length===0)return this.cancelScheduledWakeup(),null;let n=AG(this.graph,this.ruleById,t),o=this.now();if(n>o)return this.schedulePendingWakeup(n),null;this.cancelScheduledWakeup();let i=await this.store.claimPendingWave({waveId:this.createWaveId(),graphFingerprint:this.graphFingerprint,startedAt:o});if(!i)return null;let a=await this.advanceWave(i);if(a.status==="completed")await this.startNextWaveInternal();return a}async runExclusive(e){return this.operationQueue.run(e)}schedulePendingWakeup(e){if(this.scheduledWakeup?.readyAt===e)return;this.cancelScheduledWakeup();let t={readyAt:e,cancel:()=>{}};t.cancel=this.scheduleWakeup(Math.max(0,e-this.now()),async()=>{if(this.scheduledWakeup!==t)return;this.scheduledWakeup=void 0;try{await this.startNextWave()}catch(n){this.onScheduledWakeupError(n)}}),this.scheduledWakeup=t}cancelScheduledWakeup(){this.scheduledWakeup?.cancel(),this.scheduledWakeup=void 0}async advanceWave(e){if(e.graphFingerprint!==this.graphFingerprint)throw Error(`Projection wave "${e.id}" graph fingerprint does not match the finalized graph`);let t=await this.store.listWaveRules(e.id);if(t.length===0){let s=await this.store.listWaveInputs(e.id),l=yI(this.graph,this.ruleById,s);if(l.length===0)return this.completeWave(e);await this.store.putWaveRules(e.id,l),t=await this.store.listWaveRules(e.id)}if(t.every((s)=>s.status==="completed"))return this.completeWave(e,t);let n=t.find((s)=>s.status==="failed");if(n)return this.store.failWaveWithIncident({waveId:e.id,ruleId:n.ruleId,jobId:n.jobId,failureReason:"Projection rule is in a terminal failed state",failedAt:this.now()});let o=await this.findStrandedQueuedRule(t);if(o)return this.store.failWaveWithIncident({waveId:e.id,ruleId:o.rule.ruleId,jobId:o.rule.jobId,failureReason:RG(o),failedAt:this.now()});let i=Math.min(...t.filter((s)=>s.status!=="completed").map((s)=>s.level)),a=t.filter((s)=>s.level===i&&s.status==="pending");return await Promise.all(a.map((s)=>this.enqueueRule(e.id,s))),e}async findStrandedQueuedRule(e){for(let t of e){if(t.status!=="queued")continue;if(!t.jobId)return{rule:t,jobStatus:"missing"};let n=await this.queue.getStatus(t.jobId);if(!n||n.status==="completed"||n.status==="failed")return{rule:t,jobStatus:n?.status??"missing"}}return null}async completeWave(e,t){let[n,o]=await Promise.all([this.store.listWaveInputs(e.id),t?Promise.resolve(t):this.store.listWaveRules(e.id)]);return await this.beforeWaveCompletion({waveId:e.id,sourceTypes:[...new Set(n.map((i)=>i.sourceType))].sort(),changedTargetTypes:[...new Set(o.flatMap((i)=>i.changedTargets.map((a)=>a.entityType)))].sort()}),this.store.completeWave(e.id,this.now())}async enqueueRule(e,t){let n=await this.queue.enqueue({type:Do,data:{waveId:e,ruleId:t.ruleId},options:{source:"projection-scheduler",rootJobId:`projection-wave:${e}`,metadata:{operationType:"data_processing",operationTarget:t.ruleId,silent:!0},deduplication:"coalesce",deduplicationKey:`projection-wave:${e}:${t.ruleId}`,projection:{id:t.ruleId}}});await this.store.queueWaveRule(e,t.ruleId,n)}}function EG(e,t){let n=setTimeout(()=>{t()},e);return()=>clearTimeout(n)}function AG(e,t,n){let i=yI(e,t,n).reduce((s,l)=>Math.max(s,t.get(l.ruleId)?.sourceChangeBatchDelayMs??0),0);if(i===0)return 0;return n.reduce((s,l)=>Math.max(s,l.markedAt),0)+i}function PG(e,t){let n=new Map;for(let i of t){if(n.has(i.id))throw Error(`Duplicate executable projection rule "${i.id}"`);n.set(i.id,i)}let o=new Set(e.projections.map((i)=>i.id));for(let i of o)if(!n.has(i))throw Error(`Projection "${i}" has no executable rule`);for(let i of n.keys())if(!o.has(i))throw Error(`Executable projection rule "${i}" is not in the graph`);return n}function MG(e,t){return hI({projections:e.projections,edges:e.edges,rules:[...t].sort((n,o)=>n.id.localeCompare(o.id)).map((n)=>({id:n.id,version:n.version}))})}function yI(e,t,n){let o=new Map(e.projections.map((c)=>[c.id,c])),i=vI(e,(c)=>[c.from,c.to]),a=new Set(e.projections.filter((c)=>jG(c,n)).map((c)=>c.id)),s=[...a];while(s.length>0){let c=s.flatMap((u)=>i.get(u)??[]).filter((u)=>o.has(u)&&!a.has(u));for(let u of c)a.add(u);s=[...new Set(c)].sort()}let l=OG(e,a);return[...a].map((c)=>{let u=o.get(c),d=t.get(c),m=l.get(c);if(!u||!d||m===void 0)throw Error(`Cannot plan projection rule "${c}"`);return{ruleId:c,targetType:u.targetType,level:m}}).sort((c,u)=>c.level-u.level||c.ruleId.localeCompare(u.ruleId))}function jG(e,t){return e.sources.some((n)=>{let o=new Set(n.excludeTypes??[]);return t.some((i)=>!o.has(i.sourceType)&&(n.types.includes("*")||n.types.includes(i.sourceType)))})}function OG(e,t){let n=vI(e,(a)=>t.has(a.from)?[a.to,a.from]:void 0),o=new Map,i=new Set(t);while(i.size>0){let a=[...i].filter((s)=>(n.get(s)??[]).every((l)=>o.has(l))).sort();if(a.length===0)throw Error("Reachable projection graph is not acyclic");for(let s of a){let l=(n.get(s)??[]).map((u)=>o.get(u)).filter((u)=>u!==void 0),c=l.length===0?0:Math.max(...l)+1;o.set(s,c),i.delete(s)}}return o}function vI(e,t){let n=new Map;for(let o of e.edges){let i=t(o);if(!i)continue;let[a,s]=i,l=n.get(a);if(l)l.push(s);else n.set(a,[s])}return n}async function bI(e){let t=new Xd({store:e.store,queue:e.queue,graph:e.graph,rules:e.rules,createWaveId:e.createWaveId,beforeWaveCompletion:e.beforeWaveCompletion,onScheduledWakeupError:(s)=>e.logger.error("Scheduled projection wakeup failed",s),...e.scheduleWakeup&&{scheduleWakeup:e.scheduleWakeup},now:e.now}),n=new Yd({rules:e.rules,store:e.store,coordinator:t,getJobStatus:(s)=>e.queue.getStatus(s),...e.onDiagnostic&&{onDiagnostic:e.onDiagnostic},inputContext:e.inputContext,executionContext:e.executionContext,reconcileTargets:e.reconcileTargets,now:e.now});e.queue.registerHandler(Do,n,"shell");let o=()=>{},i=()=>{};try{if(e.activationMode!=="executor"){let s=async(d)=>{if(d)await e.reconcileBatches?.();await t.startNextWave()},l,c=(d)=>{if(l)return l;let m=Promise.resolve().then(()=>s(d));l=m;let p=()=>{if(l===m)l=void 0};return m.then(p,p),m},u=async()=>{if(l)return;if(await e.store.hasActiveProjectionBatch())return;await c(!1)};o=e.setWakeup(u),await c(!0),i=(e.scheduleSweep??NG)(e.sweepIntervalMs??1000,async()=>{try{await c(!0)}catch(d){e.logger.error("Projection coordination sweep failed",d)}})}}catch(s){throw i(),o(),e.queue.unregisterHandler(Do),s}e.logger.debug("Projection runtime activated",{rules:e.rules.length,mode:e.activationMode??"scheduler"});let a=!0;return{scheduler:t,dispose:()=>{if(!a)return;a=!1,i(),o(),t.dispose(),e.queue.unregisterHandler(Do)}}}function NG(e,t){let n=setInterval(()=>{t()},e);return n.unref(),()=>clearInterval(n)}var DG=250,zG=r.object({success:r.boolean()}),UG=r.object({projectionBatch:r.object({operationId:r.string().min(1),childKey:r.string().min(1)})});class tp{config;services;lifecycle;initializer;role;hooks;constructor(e,t,n,o,i,a){this.config=e,this.services=t,this.lifecycle=n,this.initializer=o,this.role=Ps(i),this.hooks=a}async boot(e){this.services.logger.debug("Starting Shell boot");let t=this.initializer;await Ls([()=>this.services.entityService.initialize(),()=>this.services.jobQueueService.initialize?.()??Promise.resolve(),()=>this.services.runtimeStateService.initialize(),()=>this.services.conversationService.initialize?.()??Promise.resolve()]);let n={...this.config.entityDisplay!==void 0&&{entityDisplay:this.config.entityDisplay},...!this.role.serves&&{executionOnly:!0}};if(await t.initializeAll(this.services.templateRegistry,this.services.entityRegistry,this.services.pluginManager,{...e?.mode==="register-only"&&{registerOnly:!0},...Object.keys(n).length>0&&{registrationContext:n}}),this.services.profileKindRegistry.finalize(),this.services.channelRegistry.finalize(),this.services.inboxRegistry.finalize(),this.services.inboxFollowUpRegistry.finalize(),await this.services.pluginManager.finalizePluginRegistrations(),this.hooks.finalizeHttpRoutes(),await this.services.projectionRuntimeSupervisor.initialize(this.services.pluginManager.getProjectionGraphSnapshot()),t.registerJobHandlers(this.services.jobQueueService,this.services.contentService,this.services.entityService),e?.mode===void 0){let i=await bI({store:this.services.entityService.getProjectionStore(),queue:this.services.jobQueueService,setWakeup:(a)=>this.services.entityService.setProjectionWakeup(a),graph:this.services.pluginManager.getProjectionGraphSnapshot(),rules:this.services.pluginManager.getProjectionRulesSnapshot(),inputContext:this.hooks.createProjectionInputContext(),executionContext:this.hooks.createProjectionExecutionContext(),reconcileTargets:(a)=>this.services.entityService.reconcileProjectionTargets(a),beforeWaveCompletion:async(a)=>{if(!this.services.messageBus.hasHandlers(ep.waveReady))return;let s=await this.services.messageBus.collect({type:ep.waveReady,payload:a,sender:"shell"});if(s.length===0||s.some((l)=>("noop"in l)||!l.success))throw Error(`Projection wave ${a.waveId} completion was not acknowledged`)},logger:this.services.logger,createWaveId:_I,now:this.hooks.projectionRuntime?.now??Date.now,...this.hooks.projectionRuntime?.scheduleWakeup&&{scheduleWakeup:this.hooks.projectionRuntime.scheduleWakeup},...this.hooks.projectionRuntime?.onDiagnostic&&{onDiagnostic:this.hooks.projectionRuntime.onDiagnostic},...this.hooks.projectionRuntime?.scheduleSweep&&{scheduleSweep:this.hooks.projectionRuntime.scheduleSweep},...this.hooks.projectionRuntime?.sweepIntervalMs!==void 0&&{sweepIntervalMs:this.hooks.projectionRuntime.sweepIntervalMs},reconcileBatches:()=>this.services.entityService.recoverProjectionBatches(async(a,s)=>(await this.services.jobQueueService.getJobsByRootJobId(a)).flatMap((c)=>{let u=UG.safeParse(JSON.parse(c.data));if(!u.success||u.data.projectionBatch.operationId!==s)return[];return[{jobId:c.id,childKey:u.data.projectionBatch.childKey,status:c.status,terminalAt:c.completedAt}]})),activationMode:this.role.projectionActivation});this.services.disposables.push(()=>i.dispose())}if(this.services.jobQueueService.finalizeHandlerRegistrations(),this.hooks.registerCoreDataSources(),this.role.serves)this.hooks.registerSystemCapabilities();if(e?.mode==="register-only"){this.services.logger.debug("Shell boot complete (register-only mode)");return}if(await this.loadIdentityServices(),!this.role.serves){this.services.jobProgressMonitor.start(),await this.services.jobQueueWorker.start(),this.services.logger.debug("Shell boot complete (worker process)");return}let o;if(e?.mode!=="startup-check"){await this.startEarlyWebserver();let i=mI();this.services.disposables.push(this.services.messageBus.subscribe(Yr.initialSyncCompleted,async(l)=>(i.resolve(zG.safeParse(l.payload).data?.success===!0),{success:!0})));let a=await this.emitPluginsRegistered(),s=await this.services.entityService.backfillMissingEmbeddings();if(this.services.logger.debug("Queued missing embedding backfill jobs",{queued:s.queued,skipped:s.skipped}),await this.services.entityService.reprojectRegisteredGroupings(),a)o=i.promise.then(async(l)=>{if(l)return this.settleStartupContent();this.services.logger.warn("Initial sync failed; ready-state defaults are not created")}).catch((l)=>{this.services.logger.error("Failed to settle startup content",l)});else await this.settleStartupContent()}else await this.prepareReadyState();if(await this.services.pluginManager.readyPlugins(),e?.mode==="startup-check"){this.services.logger.debug("Shell boot complete (startup-check mode)");return}if(await this.startRuntimeServices(),o)o.then(()=>this.startIndexReadinessMonitor()).catch((i)=>{this.services.logger.warn("Semantic index readiness monitor did not start",i)});else await this.startIndexReadinessMonitor();this.services.logger.debug("Shell boot complete")}async startEarlyWebserver(){if(!this.services.daemonRegistry.has("webserver:webserver"))return;await this.services.daemonRegistry.start("webserver:webserver"),this.services.logger.debug("Started webserver before initial sync")}async emitPluginsRegistered(){let e=await this.services.messageBus.collect({type:Yr.pluginsRegistered,payload:{timestamp:new Date().toISOString(),pluginCount:this.services.pluginManager.getAllPluginIds().length},sender:"shell"});return this.services.logger.debug("Emitted plugins registered event"),e.some((t)=>("data"in t)&&wI.safeParse(t.data).data?.initialSyncPending===!0)}async settleStartupContent(){await this.prepareReadyState(),await this.services.messageBus.send({type:Yr.startupContentSettled,payload:{timestamp:new Date().toISOString()},sender:"shell",broadcast:!0}),this.services.logger.debug("Emitted startup content settled event")}async loadIdentityServices(){await Ls([()=>this.services.identityService.refreshCache(),()=>this.services.profileService.refreshCache(),()=>this.services.canonicalIdentityService.refreshCache()]),this.services.logger.debug("Identity services loaded")}async initializeIdentityServices(){await Ls([()=>this.services.identityService.initialize(),()=>this.services.profileService.initialize(),()=>this.services.canonicalIdentityService.refreshCache()]),this.services.logger.debug("Identity services initialized")}async prepareReadyState(){await this.initializeIdentityServices();let e=await SI(this.services.templateRegistry,this.services.entityService);if(e>0)this.services.logger.debug(`Materialized ${e} prompt entities`)}async startRuntimeServices(){for(let e of["shell:recurring-checks","shell:guest-retention"])if(this.services.daemonRegistry.has(e))await this.services.daemonRegistry.start(e);if(await this.services.pluginManager.startPluginDaemons(),this.role.executes)await this.services.jobQueueWorker.start();this.services.jobProgressMonitor.start(),await this.services.batchJobManager.start()}async startIndexReadinessMonitor(){await this.lifecycle.fork(this.runIndexReadinessMonitor())}runIndexReadinessMonitor(){let{entityService:e,logger:t}=this.services;return se.tryPromise({try:(n)=>e.awaitIndexReady({intervalMs:DG,signal:n}),catch:(n)=>n}).pipe(se.tap((n)=>se.sync(()=>{if(n.degraded)t.warn("Semantic index ready with degraded embeddings",n);else t.debug("Semantic index ready",n)})),se.catch((n)=>se.sync(()=>{t.warn("Semantic index readiness monitor stopped",n)})))}}class TI{handlers=new Map;register(e,t){this.handlers.set(e,t)}unregister(e){this.handlers.delete(e)}getTypes(){return Array.from(this.handlers.keys())}async get(e,t,n){let o=this.handlers.get(e);if(!o)throw Error(`Unknown insight type: ${e}. Available: ${this.getTypes().join(", ")}`);let i=n==="public"?xI(t,{publishedOnly:!0,visibilityScope:n}):t;return o(i,n)}}function II(e){let t=new TI;return t.register("overview",qG),t.register("publishing-cadence",LG),t.register("content-health",(n,o)=>$G(n,o,e)),t}async function qG(e,t){let n=await e.getEntityCounts(t),o={},i=0;for(let{entityType:f,count:g}of n)o[f]=g,i+=g;let a=await rp(e,t),s=Date.now(),l=s-604800000,c=s-2592000000,u=0,d=0;for(let f of a){let g=new Date(f.created).getTime();if(g>=l)u++;if(g>=c)d++}let m=CI(a),p=a.filter((f)=>f.metadata.status==="published");return{entityCounts:o,totalEntities:i,recentActivity:{last7days:u,last30days:d},contentHealth:{drafts:m.length,published:p.length}}}async function LG(e,t){let n=await rp(e,t),o=new Map;for(let a of n){let s=new Date(a.created);if(isNaN(s.getTime()))continue;let l=`${s.getUTCFullYear()}-${String(s.getUTCMonth()+1).padStart(2,"0")}`,c=o.get(l);if(!c)c={},o.set(l,c);c[a.entityType]=(c[a.entityType]??0)+1}return{months:Array.from(o.entries()).sort((a,s)=>s[0].localeCompare(a[0])).map(([a,s])=>{let l=0;for(let c of Object.values(s))l+=c;return{month:a,counts:s,total:l}})}}async function $G(e,t,n){let o=await rp(e,t),i=CI(o).map((c)=>({id:c.id,entityType:c.entityType,title:typeof c.metadata.title==="string"?c.metadata.title:c.id,created:c.created})),a=Date.now(),s=a-7776000000,l=o.filter((c)=>{if(n.getEntityTypeConfig(c.entityType).binaryStorage)return!1;let u=new Date(c.updated).getTime();return!isNaN(u)&&u<s}).map((c)=>({id:c.id,entityType:c.entityType,title:typeof c.metadata.title==="string"?c.metadata.title:c.id,updated:c.updated,daysSinceUpdate:Math.floor((a-new Date(c.updated).getTime())/86400000)}));return{drafts:i,stale:l}}function CI(e){return e.filter((t)=>t.metadata.status==="draft")}async function rp(e,t){let n=e.getEntityTypes(),o=[];for(let i of n){let a=await e.listEntities({entityType:i,options:{limit:1000,filter:{visibilityScope:t}}});o.push(...a)}return o}class ta{parse;idOf;items=new Map;constructor(e,t){this.parse=e,this.idOf=t}register(e){let t=this.parse(e);this.items.set(this.keyFor(t.pluginId,this.idOf(t)),t)}unregister(e,t){if(t!==void 0){this.items.delete(this.keyFor(e,t));return}let n=`${e}:`;for(let o of this.items.keys())if(o.startsWith(n))this.items.delete(o)}list(){return Array.from(this.items.values()).sort((e,t)=>e.priority-t.priority||e.label.localeCompare(t.label))}keyFor(e,t){return`${e}:${t}`}}class np extends ta{constructor(){super((e)=>kI.parse(e),(e)=>e.url)}}class op extends ta{constructor(){super((e)=>RI.parse(e),(e)=>e.id)}}function EI(e,t){return{enqueueBatch:e.enqueueBatch.bind(e),getActiveBatches:e.getActiveBatches.bind(e),getBatchStatus:e.getBatchStatus.bind(e),getActiveJobs:t.getActiveJobs.bind(t),getRecentJobs:t.getRecentJobs.bind(t),getStatus:t.getStatus.bind(t)}}var FG=["/health","/images"],BG=new Set([AI]),GG=new Set(PI),JG=new Set(["GET","POST","PUT","DELETE"]);function MI(e){let t=[];for(let[n,{plugin:o}]of e.getAllPlugins()){let i,a;try{i=o.getWebRoutes?.()??[],a=o.getApiRoutes?.()??[]}catch(s){throw Error(`Failed to collect HTTP route declarations from plugin "${n}"`,{cause:s})}t.push({pluginId:n,webRoutes:i,apiRoutes:a})}return t}function WG(e){return BG.has(e)||FG.some((t)=>e===t||e.startsWith(`${t}/`))}function ip(e,t,n=!0){let o;try{o=new URL(e,"http://route.invalid").pathname}catch{o=void 0}if(!e.startsWith("/")||e.includes("//")||e.includes("?")||e.includes("#")||e.includes("%")||e.length>1&&e.endsWith("/")||e.trim()!==e||o!==e||n&&WG(e))throw Error(`Invalid HTTP route path "${e}" declared by plugin "${t}"`)}function jI(e,t,n){if(!e.has(t))throw Error(`Invalid HTTP route method "${t}" declared by plugin "${n}"`)}function HG(e,t){if(e!=="exact"&&e!=="prefix")throw Error(`Invalid HTTP route match "${e}" declared by plugin "${t}"`)}function VG(e,t){ip(t.path,e.pluginId);let n=t.method??"GET";jI(GG,n,e.pluginId);let o=t.match??"exact";if(HG(o,e.pluginId),typeof t.handler!=="function")throw Error(`Invalid HTTP route handler for "${t.path}" declared by plugin "${e.pluginId}"`);return Object.freeze({kind:"handler",ownerPluginId:e.pluginId,fullPath:t.path,method:n,match:o,sharedHostAdmission:t.public===!0?"admit":"deny",...t.preview===!0?{preview:!0}:{},handler:t.handler})}function ZG(e,t){ip(t.path,e.pluginId,!1);let n=`/api/${e.pluginId}${t.path}`;if(ip(n,e.pluginId),jI(JG,t.method,e.pluginId),typeof t.tool!=="string"||t.tool.trim()==="")throw Error(`Invalid HTTP route tool for "${n}" declared by plugin "${e.pluginId}"`);return Object.freeze({kind:"tool",ownerPluginId:e.pluginId,fullPath:n,method:t.method,match:"exact",sharedHostAdmission:t.public?"admit":"deny",definition:Object.freeze({...t})})}function KG(e){let t=new Map;for(let n of e){let o=`${n.method} ${n.fullPath}`,i=t.get(o);if(i!==void 0)throw Error(`HTTP route conflict for ${o} between plugins "${i}" and "${n.ownerPluginId}"; give one declaration a different method or path`);t.set(o,n.ownerPluginId)}}function QG(e){return Object.freeze(e.map((t)=>Object.freeze({ownerPluginId:t.ownerPluginId,kind:t.kind,method:t.method,fullPath:t.fullPath,match:t.match,sharedHostAdmission:t.sharedHostAdmission})))}class Fs{routes;manifest;apiRoutes;webRoutes;static createFresh(){return new Fs}constructor(){}finalize(e){if(this.routes!==void 0)throw Error("HTTP route registry has already been finalized");let t=[],n=[],o=[];for(let i of e){for(let a of i.webRoutes)t.push(VG(i,a)),n.push(Object.freeze({pluginId:i.pluginId,fullPath:a.path,definition:Object.freeze({...a})}));for(let a of i.apiRoutes){let s=ZG(i,a);t.push(s),o.push(Object.freeze({pluginId:i.pluginId,fullPath:s.fullPath,definition:s.definition}))}}return KG(t),this.routes=Object.freeze(t),this.manifest=QG(this.routes),this.webRoutes=Object.freeze(n),this.apiRoutes=Object.freeze(o),this.routes}getSnapshot(){if(this.routes===void 0)throw Error("HTTP route registry has not been finalized");return this.routes}getManifest(){if(this.manifest===void 0)throw Error("HTTP route registry has not been finalized");return this.manifest}getApiRoutes(){if(this.apiRoutes===void 0)throw Error("HTTP route registry has not been finalized");return[...this.apiRoutes]}getWebRoutes(){if(this.webRoutes===void 0)throw Error("HTTP route registry has not been finalized");return[...this.webRoutes]}}function OI(e,t){e.addFinalizer(()=>t.pluginManager.shutdownPlugins()),e.addFinalizer(()=>t.jobServicesLifecycle.closeRuntime()),e.addFinalizer(()=>t.agentService.shutdown?.()),e.addFinalizer(()=>t.daemonRegistry.unregister("shell:guest-retention")),e.addFinalizer(()=>t.daemonRegistry.unregister("shell:recurring-checks"))}var YG=r.discriminatedUnion("kind",[r.object({kind:r.literal("all")}).strict().describe("Search across all entity types"),r.object({kind:r.literal("type"),entityType:r.string().min(1).describe("Entity type to search")}).strict().describe("Search within one entity type")]),DI=r.object({query:r.string().describe("Search term"),scope:YG.describe("Structured search scope. Use { kind: 'all' } for broad search across all entity types. Use { kind: 'type', entityType } only when the user asks for a specific entity type."),limit:r.number().optional().describe("Maximum number of results"),minScore:r.number().min(0).optional().describe("Minimum relevance score. Default is 0.5; lower it only for exploratory or loose recall when weak candidates are acceptable."),includeUngenerated:r.boolean().optional().describe("Include queued/failed generation stubs in results")}),zI=r.object({entityType:r.string().describe("Entity type"),id:r.string().describe("Entity ID, slug, or title")}),UI=r.object({entityType:r.string().describe("Entity type to list"),status:r.string().optional().describe("Filter by status. Omit unless the user asks for a known status; do not invent generic statuses. For wish statuses: new, planned, in-progress, done, declined."),limit:r.number().optional().describe("Maximum number of results (default: 20)")}),XG=r.object({kind:r.literal("upload").describe("Upload ref kind"),id:r.string().min(1).describe("Upload ID")}),qI=r.object({kind:r.literal("user-message").describe("Use verbatim text already supplied by the user. The server reads the stored message; do not copy its body into tool arguments."),messageId:r.string().min(1).optional().describe("Stored user message ID in this conversation; omit for the latest user message."),boundaryMode:r.enum(["literal","lines"]).optional().describe("Use lines for standalone delimiter lines: supply marker text without newline characters. The server excludes the opening line and its line ending, and stops at the start of the closing line, preserving every byte between them, including final newlines. Omit or use literal for inline text boundaries."),startAfter:r.string().min(1).optional().describe("Exact unique opening boundary, excluded from saved text. In lines mode, supply the whole marker line WITHOUT newline characters. In literal mode, supply the exact prefix to exclude. Omit to start at the beginning of the message."),endBefore:r.string().min(1).optional().describe("Exact unique closing boundary, excluded from saved text. In lines mode, supply the whole marker line WITHOUT newline characters; preceding content newlines are preserved. In literal mode, supply the exact suffix to exclude. Omit to end at the end of the message."),contentHash:r.string().min(1).optional().describe("Internal source hash returned with the confirmation; omit on the initial request.")}).strict(),eJ=r.discriminatedUnion("kind",[r.object({kind:r.literal("text").describe("Store exact/direct user-provided content without generation"),content:r.string().min(1).describe("Literal content for a direct save request without a stored user-message source. For pasted text already in this conversation, prefer source.kind user-message with exact boundaries instead of reproducing the body here.")}).strict(),qI,r.object({kind:r.literal("url").describe("Create URL/domain-backed entities such as links"),url:r.string().min(1).describe("URL or domain to create from; preserve a bare domain as provided instead of adding a scheme.")}).strict(),r.object({kind:r.literal("upload").describe("Use extract-markdown to import upload text into a note, or preserve only when the user explicitly wants to save the uploaded file/document bytes themselves. Do not use for saving a previous assistant summary about an upload; use prior-response for that."),upload:XG.describe("Exact upload candidate object from the current conversation"),transform:r.enum(["extract-markdown","preserve"]).describe("extract-markdown imports upload text into a note-like entity; preserve saves raw uploaded bytes via the registered upload-save handler and derives the durable entity type from media type. Use preserve only for explicit file/document preservation, not for saving an assistant summary response.")}).strict(),r.object({kind:r.literal("prior-response").describe("Save a previous assistant response as durable content, especially an assistant summary or answer about an upload."),messageId:r.string().min(1).optional().describe("Stored assistant message ID; omit for latest savable")}).strict()]),tJ=r.discriminatedUnion("kind",[r.object({kind:r.literal("prompt").describe("Generate a new non-image durable entity from a broad prompt with no durable source entity. Use this for general topical social/newsletter/blog/deck generation. This branch has no source field; use prompt-from-source only after resolving a specific existing content entity."),entityType:r.string().min(1).describe("Entity type to generate from the prompt. Do not use image here; use standalone-image or cover-image."),title:r.string().optional().describe("Title for the generated entity"),prompt:r.string().min(1).describe("Prompt for creating new generated content. Do not use for saving/importing existing uploads or prior responses.")}).strict(),r.object({kind:r.literal("prompt-from-source").describe("Generate a new non-image durable entity from a specific resolved existing content entity. Use when the user asks to generate from/based on a source, including requests like 'create a newsletter based on my latest blog post'. After resolving the source with a tool result, call this operation in the same turn; do not merely say you can generate it."),entityType:r.string().min(1).describe("Entity type to generate from the source and prompt. Do not use image here; use standalone-image or cover-image."),title:r.string().optional().describe("Title for the generated entity"),source:r.object({entityType:r.string().min(1).describe("Resolved content source entity type, such as post for a newsletter from a blog post. Do not use brain-character or anchor-profile."),entityId:r.string().min(1).describe("Resolved source entity ID copied from a prior tool result or typed entity ref; never an upload id, filename, guessed slug, or future placeholder.")}).strict().describe("Existing durable source entity to ground this generation. Use only resolved entity refs, not uploads, filenames, profile/brain-character context, conversation-only context, unknown sources, or guessed sources."),prompt:r.string().min(1).describe("Prompt for creating new generated content from the resolved source. Do not use for saving/importing existing uploads or prior responses.")}).strict(),r.object({kind:r.literal("standalone-image").describe("Generate a standalone image that is not attached to another entity. Do not use this as a cover image substitute; requested covers require cover-image after the target entity exists."),title:r.string().optional().describe("Title for the generated image"),prompt:r.string().min(1).describe("Prompt for creating an unattached image. Not for cover images requested for a generated post/entity.")}).strict(),r.object({kind:r.literal("cover-image").describe("Generate an image and attach it to an existing entity as coverImageId. Use only after the target entity already exists and its real entityId is known; do not use in the same initial turn as generating that target entity."),target:r.object({entityType:r.string().min(1).describe("Existing target entity type. Use the actual type of the entity being covered: social-post for LinkedIn/social posts, post for blog posts, etc."),entityId:r.string().min(1).describe("Existing target entity ID copied from a prior tool result or typed entity ref; never a placeholder or guessed future id")}).strict().describe("Existing entity that should receive the generated coverImageId"),title:r.string().optional().describe("Title for the generated image"),prompt:r.string().min(1).describe("Prompt for creating the cover image")}).strict(),r.object({kind:r.literal("attachment").describe("Generate a deterministic durable artifact from an existing entity attachment provider"),source:r.object({entityType:r.string().min(1).describe("Source entity type"),entityId:r.string().min(1).describe("Canonical source entity ID copied from a prior tool result or typed entity ref; never an upload id, filename, guessed slug, or future placeholder")}).strict().describe("Existing durable entity whose attachment provider should render the artifact. Use only resolved entity refs, not uploads or conversation-only context."),attachmentType:r.string().min(1).describe('Source artifact type such as "carousel", "printable", or "og-image"'),title:r.string().optional().describe("Title for the generated artifact"),replace:r.boolean().optional().describe("Set true for regenerate, replace, refresh, or update requests so a deterministic artifact is regenerated instead of reused")}).strict()]),LI=r.object({entityType:r.string().describe("Entity type to create. Use wish for explicitly saved or tracked unmet requested capabilities or outcomes."),title:r.string().optional().describe("Title for a new entity."),visibility:NI.optional().describe("Content visibility. Omit for public. Use shared for team/collaborator content readable by Trusted and Admin callers. Use restricted for private/admin-only content."),source:eJ.describe("Concrete source selector. Use exactly one source branch. For AI generation or source-derived artifacts, use system_generate instead."),replace:r.boolean().optional().describe("Create a new copy intentionally"),confirmed:r.literal(!0).optional().describe("Confirm the creation"),confirmationToken:r.string().optional().describe("Internal confirmation token returned by the confirmation flow")}).strict(),$I=r.object({operation:tJ.describe("Generation operation selector. Use prompt for broad non-image AI-generated entities with no source, prompt-from-source for generation from a resolved existing entity, standalone-image for unattached images, cover-image for generated covers on existing entities, and attachment for deterministic source-derived artifacts; for regenerate/replace/refresh artifact requests use attachment with replace:true."),confirmed:r.literal(!0).optional().describe("Confirm generation"),confirmationToken:r.string().optional().describe("Internal confirmation token returned by the confirmation flow")}).strict(),rJ=r.object({oldText:r.string().min(1).describe("Exact text occurring once in the original stored Markdown. Include enough context to be unique."),newText:r.string().describe("Literal replacement text; empty string deletes oldText.")}).strict(),ap=r.object({entityType:r.string().describe("Entity type"),id:r.string().describe("Entity ID, slug, or title"),fields:r.record(r.string(),r.unknown()).optional().describe("Partial frontmatter fields to update. Use this for status, title, coverImageId, ogImageId, and metadata changes such as approving an agent. To set an existing image as an entity cover, update fields.coverImageId to that image id. To remove or clear a cover image, set fields.coverImageId to null, not an empty string. Do not use fields for anchor-profile; anchor-profile updates require full markdown content replacement via content."),content:r.string().optional().describe("Full replacement text you wrote yourself. Text without frontmatter replaces the body and keeps the stored frontmatter; text with frontmatter replaces the whole document. When the user supplied the replacement text, use source instead of copying it here. For small changes, use edits instead of regenerating the whole document."),edits:r.array(rJ).min(1).max(50).optional().describe("Preferred for small content edits, especially long notes. Exact, unique, non-overlapping replacements matched against the original Markdown, applied atomically after confirmation. Fetch the entity first. Unchanged text is preserved without regeneration."),source:qI.optional().describe("Full replacement taken verbatim from a user message, for large rewrites the user supplied. Select the text with exact boundaries instead of copying it into content. Text without frontmatter replaces the body and keeps the stored frontmatter; text with frontmatter replaces the whole document."),confirmed:r.literal(!0).optional().describe("Confirm the update"),confirmationToken:r.string().optional().describe("Internal confirmation token returned by the confirmation flow"),contentHash:r.string().optional().describe("Content hash for optimistic concurrency")}),FI=r.object({entityType:r.string().describe("Entity type"),id:r.string().describe("Entity ID"),confirmed:r.literal(!0).optional().describe("Confirm the deletion"),confirmationToken:r.string().optional().describe("Internal confirmation token returned by the confirmation flow")}),Mee=r.object({entityType:r.string().describe("Entity type to extract"),source:r.string().optional().describe("Source entity ID \u2014 omit for batch"),mode:r.enum(["derive","rebuild"]).optional().describe("Batch mode: project incrementally or rebuild from scratch"),confirmed:r.literal(!0).optional().describe("Confirm destructive rebuild"),confirmationToken:r.string().optional().describe("Internal confirmation token returned by the confirmation flow")}),BI=r.object({batchId:r.string().optional().describe("Specific batch ID to check"),jobTypes:r.array(r.string()).optional().describe("Filter by job types")}),GI=r.object({type:r.string().describe("Type of insight to retrieve. Built-in: overview, publishing-cadence, content-health. Plugins may register additional types.")}),nJ=r.object({entityType:r.string().optional(),entityId:r.string().optional(),attachmentType:r.string().optional()}),oJ=r.object({mediaType:r.string(),url:r.string(),downloadUrl:r.string().optional(),previewUrl:r.string().optional(),filename:r.string().optional(),sizeBytes:r.number().optional(),source:nJ.optional()}),jee=r.object({entityId:r.string().optional(),status:r.enum(["created","generating"]),jobId:r.string().optional(),attachment:oJ.optional()}),Oee=r.object({status:r.literal("extracting"),jobId:r.string(),entityType:r.string(),source:r.string().optional(),mode:r.enum(["derive","rebuild"]).optional()});function Mr(e,t,n,o){try{e.permissionService.assertEntityActionAllowed(t,n,o.userPermissionLevel);return}catch(i){if(i instanceof JI||i instanceof Error)return{success:!1,error:i.message};throw i}}async function Gs(e,t,n){let o=n.conversationId??n.channelId;if(!o)return{success:!1,error:"Conversation message is not accessible in this conversation or does not exist."};let i=await e.conversationService.getMessages(o,{limit:100}),a=t.kind==="user-message",s=a?i.filter((p)=>{if(p.role!=="user")return!1;let f=n.userPermissionLevel??"public";if(f==="admin")return!0;let g=Bs(p.metadata)?.userPermissionLevel;return(g==="public"||g==="trusted"||g==="admin")&&e.permissionService.hasPermission(f,g)}):i.filter(WI),l=t.messageId?s.find((p)=>p.id===t.messageId):s.at(-1);if(!l)return{success:!1,error:"Conversation message is not accessible in this conversation or does not exist."};if(!a)return{success:!0,messageId:l.id,content:l.content};let c=(p,f,g)=>{if(p===void 0)return f;if(t.boundaryMode==="lines"){if(/[\r\n]/.test(p))return-1;let v=0,x=-1;for(let _ of l.content.split(/(?<=\n)/)){if(_.replace(/\r?\n$/,"")===p){if(x>=0)return-1;x=v+(g?_.length:0)}v+=_.length}return x}let h=l.content.indexOf(p);return h>=0&&h===l.content.lastIndexOf(p)?h+(g?p.length:0):-1},u=c(t.startAfter,0,!0),d=c(t.endBefore,l.content.length,!1);if(u<0||d<0||u>=d)return{success:!1,error:"User-message boundaries must each occur exactly once and select non-empty content in order. In lines mode, use complete marker lines without newline characters. Request clarification if the intended content cannot be selected uniquely."};let m=l.content.slice(u,d);if(t.contentHash&&t.contentHash!==yn(m))return{success:!1,error:"User-message source changed after the proposal. Request the change again and confirm the new approval."};return{success:!0,messageId:l.id,content:m}}function Js(e,t){return{...e,messageId:t.messageId,contentHash:yn(t.content)}}var iJ="system",HI=r.record(r.string(),r.unknown()),aJ=r.looseObject({fields:HI});function jr(e,t,n,o,i={}){let{visibility:a="admin",sideEffects:s}=i;return{name:`${iJ}_${e}`,description:t,inputSchema:n.shape,handler:async(l,c)=>{let u=n.safeParse(l);if(!u.success)return{success:!1,error:`Invalid input: ${u.error.issues.map((d)=>`${d.path.join(".")}: ${d.message}`).join(", ")}`};try{return await o(u.data,c)}catch(d){return{success:!1,error:Ce(d)}}},visibility:a,...s?{sideEffects:s}:{}}}async function Ws(e,t,n,o){let i={interfaceType:o.interfaceType,actor:o.actor,...o.channelId&&{channelId:o.channelId},...o.channelName&&{channelName:o.channelName}},a=await t(n,i);if(a.kind==="handled")return{kind:"handled",result:a.result};let s=a.input;if(s.visibility!==n.visibility)return{kind:"error",result:{success:!1,error:"Create interceptor changed or dropped the requested entity visibility."}};let l=Mr(e,s.entityType,"create",o);if(l)return{kind:"error",result:l};return{kind:"continue",createInput:s}}function Jn(e,t){if(e.entityRegistry.hasEntityType(t))return;let n=e.entityService.getEntityTypes();return{success:!1,error:`Entity type "${t}" is not available in this brain. Available types: ${n.join(", ")}.`}}function zo(e){let t={...e.conversationId?{conversationId:e.conversationId}:{},...e.channelId?{channelId:e.channelId}:{},...e.runId?{runId:e.runId}:{},...e.toolCallId?{toolCallId:e.toolCallId}:{}};return Object.keys(t).length>0?t:void 0}function sp(e,t){if(t.getEntityTypeConfig(e.entityType).binaryStorage)return{...e,content:`[binary ${e.entityType} data \u2014 use metadata for ${e.entityType} info]`};return e}function Wn(e){if(e===void 0)return;let t=e.trim();return t.length>0?t:void 0}function VI(e){if(e.fields!==void 0)return{...e};if(!e.content)return{};try{let t=JSON.parse(e.content),n=aJ.safeParse(t);if(n.success)return{fields:n.data.fields};let o=HI.safeParse(t);if(o.success)return{fields:o.data}}catch{}return{content:e.content}}var sJ={base:"note"};function ZI(e){return sJ[e]??e.replaceAll("-"," ")}function Hs(e){return[e.metadata.title,e.metadata.name,e.metadata.subject,e.metadata.slug].find((o)=>typeof o==="string"&&o.trim().length>0)??e.id}function KI(e){return!!e&&Object.keys(e.shape).length>0}async function QI(e,t,n){if(!n)return!1;let o=await e.conversationService.getMessages(n,{limit:100});for(let i of o){let s=Bs(i.metadata)?.attachments;if(!Array.isArray(s))continue;for(let l of s){if(!gr(l))continue;let c=l.source;if(!gr(c))continue;if(c.kind===t.kind&&c.id===t.id)return!0}}return!1}var lJ={namespace:"upload",refKind:"upload",routePath:"/api/chat/uploads"};function cJ(e){return{summary:`Save uploaded file${e.title?` as "${e.title}"`:""}?`,preview:[`Filename: ${e.filename}`,`Media type: ${e.mediaType}`,`Entity type: ${e.entityType}`,`Visibility: ${e.visibility??"public"}`,...e.title?[`Title: ${e.title}`]:[]].join(`
|
|
182
182
|
`)}}function uJ(e){let{entityType:t,title:n,visibility:o,prompt:i,content:a,url:s,from:l}=e,c=n?` "${n}"`:` ${t}`,u=`${i?"Generate":"Create"}${c}?`,d=l?.kind==="entity-attachment"?l:void 0,m=[`Entity type: ${t}`,`Visibility: ${o??"public"}`,...n?[`Title: ${n}`]:[],...s?[`URL: ${s}`]:[],...l?.kind==="upload"?["Upload: uploaded file"]:[],...d?[`Source attachment: ${d.sourceEntityType}/${d.sourceEntityId} (${d.attachmentType})`]:[],...i?[`Prompt: ${i}`]:[],...a?[`Content preview: ${a.slice(0,500)}`]:[]];return{summary:u,preview:m.join(`
|
|
183
183
|
`)}}function dJ(e){switch(e.kind){case"text":return{content:e.content};case"url":return{url:e.url};case"upload":return{from:e.upload,uploadRef:e.upload,transform:e.transform};case"prior-response":case"user-message":return{conversationMessageRef:e}}}function pJ(e){if(e.source.kind==="user-message"){if(!e.resolvedMessageId||e.content===void 0)throw Error("User-message source was not resolved before confirmation");return Js(e.source,{messageId:e.resolvedMessageId,content:e.content})}if(e.source.kind==="prior-response"){let t=e.source.messageId??e.resolvedMessageId;return{kind:"prior-response",...t?{messageId:t}:{}}}return e.source}async function mJ(e,t){let n={interfaceType:t.interfaceType,actor:t.actor,...t.channelId&&{channelId:t.channelId},...t.channelName&&{channelName:t.channelName}};return e.handler({upload:e.upload,...e.title&&{title:e.title},...e.visibility!==void 0?{visibility:e.visibility}:{}},n)}async function gJ(e,t,n){let{entityService:o,entityRegistry:i}=e,a=Qr(t.title??`${t.entityType}-${Date.now()}`),s=i.getEffectiveFrontmatterSchema(t.entityType);try{let l={deduplicateId:!0,...n?{eventContext:n}:{}};return{success:!0,data:{entityId:(t.content&&KI(s)?await o.createEntityFromMarkdown({input:{entityType:t.entityType,id:a,markdown:t.content,...t.visibility!==void 0?{visibility:t.visibility}:{}},options:l}):await o.createEntity({entity:{id:a,entityType:t.entityType,content:t.content??"",metadata:{title:t.title??a},...t.visibility!==void 0?{visibility:t.visibility}:{},created:new Date().toISOString(),updated:new Date().toISOString()},options:l})).entityId,status:"created"}}}catch(l){return{success:!1,error:Ce(l,"Failed to create entity")}}}function vn(e){return{kind:"error",result:{success:!1,error:e}}}async function fJ(e,t,n){let{content:o,url:i,from:a,uploadRef:s,conversationMessageRef:l,transform:c}=dJ(t.source),u=l?await Gs(e,l,n):void 0;if(u&&!u.success)return{kind:"error",result:u};let d=u?.success===!0?u.content:o;if(c==="extract-markdown"&&(!s||!e.entityRegistry.getEntityTypeConfig(t.entityType).markdownImport)){let m=e.entityRegistry.getAllEntityTypes().filter((p)=>e.entityRegistry.getEntityTypeConfig(p).markdownImport);return vn(`Transform "extract-markdown" requires an upload ref and a type declaring markdownImport. Available: ${m.join(", ")||"none"}. Omit transform for raw file promotion.`)}if(!d&&!i&&!a)return vn('Provide `source` with kind "user-message", "text", "url", "prior-response", or "upload". Use system_generate for generated content or artifacts.');return{kind:"ok",value:{content:d,url:i,from:a,uploadRef:s,transform:c,resolvedMessageId:u?.success===!0?u.messageId:void 0}}}async function hJ(e,t,n){if(!await QI(e,t.uploadRef,n.conversationId??n.channelId))return vn("Upload ref is not accessible in this conversation or no longer exists.");if(t.transform!=="preserve")return{kind:"ok",value:{entityType:t.entityType,uploadPreserve:void 0}};let i;try{i=await e.runtimeUploads.scoped(lJ).readRecord(t.uploadRef.id)}catch{return vn("Upload ref not found")}let a=e.entityRegistry.getUploadSaveHandler(i.mediaType);if(!a)return vn(`No installed plugin can save uploads with media type "${i.mediaType}".`);return{kind:"ok",value:{entityType:a.entityType,uploadPreserve:{upload:t.uploadRef,filename:i.filename,mediaType:i.mediaType,handler:a.handler}}}}function yJ(e,t,n){let o=t?Zs(t):void 0;if(e!==void 0&&o!==void 0&&e!==o)return vn(`Conflicting entity visibility: system_create requested "${e}" but the source frontmatter declares "${o}".`);let i=e??o,a=i??"public";if(!Vs(n.userPermissionLevel,a))return vn(`Cannot create entity with visibility "${a}" \u2014 caller permission "${n.userPermissionLevel??"public"}" is not allowed to write at that level.`);return{kind:"ok",value:i}}async function vJ(e,t,n){if(n||t.replace)return;let o=t.title?Qr(t.title):void 0;if(!o)return;if(!await e.entityService.getEntity({entityType:t.entityType,id:o}))return;return{success:!1,error:`A ${t.entityType} already exists for "${o}". To change its fields or status, use system_update; pass replace:true to create a new copy intentionally.`}}async function bJ(e,t,n){if(!(t.source.kind==="upload"&&t.source.transform==="preserve")){let C=Jn(e,t.entityType);if(C)return{kind:"error",result:C}}let i=await fJ(e,t,n);if(i.kind==="error")return i;let{content:a,url:s,from:l,uploadRef:c,transform:u,resolvedMessageId:d}=i.value,m=c?await hJ(e,{entityType:t.entityType,uploadRef:c,transform:u},n):void 0;if(m?.kind==="error")return m;let p=m?.value.entityType??t.entityType,f=m?.value.uploadPreserve,g=Jn(e,p);if(g)return{kind:"error",result:g};let h=yJ(t.visibility,a,n);if(h.kind==="error")return h;let v=Wn(t.title),x=t.replace===!0,_={entityType:p,...v&&{title:v},...h.value!==void 0?{visibility:h.value}:{},...a&&{content:a},...s&&{url:s},...l&&{from:l},...u&&{transform:u},...x&&{replace:x}},y=Mr(e,_.entityType,"create",n);if(y)return{kind:"error",result:y};let w=e.entityRegistry.getCreateInterceptor(_.entityType);if(!_.content&&!w&&!f)return vn('URL or upload source creation is supported only for entity types that explicitly handle it. Provide source kind "text" for this entity type, or use system_generate for generated content/artifacts.');let S=await vJ(e,_,w);if(S)return{kind:"error",result:S};return{kind:"ok",prepared:{createInput:_,resolvedMessageId:d,interceptor:w,eventContext:zo(n),...f&&{uploadPreserve:f}}}}function YI(e){let t=en({label:"create",requestNoun:"creation"});return jr("create","Create a new entity from existing material. Never create a duplicate to save edits: use system_update for entities already created or imported in this conversation, even while an upload import is generating. Requires confirmation; call this tool without confirmed to request that confirmation instead of asking for plain-text approval. Use visibility shared for team/collaborator content, restricted for private/admin-only content, and omit it for public content; keep visibility separate from exact source text. Use source to choose exactly one concrete source: user-message for verbatim content already pasted in this conversation (the server extracts the stored text without model copying), text for literal content without a stored message source, url for URL-first flows, prior-response for saving a previous assistant response, or upload with transform extract-markdown to import text into a note or transform preserve to save raw uploaded bytes as their durable file entity. Entity-specific instructions may direct proactive capture of the user's request itself; in that case the request is concrete text and no separate save verb is required. Use system_generate for AI generation, generated images, cover images, and source-derived artifacts such as carousel/printable PDFs or OG images. If the user includes content in the same direct save request, use source.kind user-message, omitting messageId for the latest user message. For standalone delimiter lines, use boundaryMode lines with startAfter/endBefore set to the exact marker line text WITHOUT newline characters; the server preserves all intervening bytes, including final newlines. For inline content, use literal startAfter/endBefore boundaries to exclude the save instruction. Omit boundaries only when saving the whole message. Never retype, shorten, correct, or include delimiter text in pasted source material, and never ask for a smaller copy just because it is long. For 'Save this as a note: ...', startAfter can be the exact 'Save this as a note: ' prefix. If boundaries are ambiguous, ask for clarification. If the user says save it/that/this after your immediately preceding upload summary/answer, use entityType note with source.kind prior-response unless they explicitly ask to save the uploaded file/document itself; do this even when the prior answer says there was limited readable content, and do not ask whether they meant the summary or the file after you just summarized/answered about the upload. A bare upload receipt like 'I got filename. What would you like me to do?' is not a summary/answer: for a following 'save it', preserve the latest uploaded file itself with upload transform preserve (image uploads as entityType image). Only use source.kind upload when the runtime supplies an actual upload reference/attachment; if the user message merely contains a pasted uploaded-file transcript with readable content, use source.kind user-message with boundaries selecting that visible content. On the initial create request, do not pass confirmed; the tool will return confirmation args after the user confirms.",LI,async(n,o)=>{let i=await bJ(e,n,o);if(i.kind==="error")return i.result;let{createInput:a}=i.prepared,{resolvedMessageId:s,interceptor:l,eventContext:c,uploadPreserve:u}=i.prepared;if(n.confirmed){let d=t.validateConfirmed(n.confirmationToken,n);if(d)return d}else{let d=u?cJ({...a.title&&{title:a.title},filename:u.filename,mediaType:u.mediaType,entityType:a.entityType,visibility:a.visibility}):uJ(a),m=pJ({source:n.source,...s&&{resolvedMessageId:s},...a.content!==void 0?{content:a.content}:{}}),p=t.buildArgs((f)=>({entityType:a.entityType,...a.title&&{title:a.title},...a.visibility!==void 0?{visibility:a.visibility}:{},source:m,...a.replace&&{replace:a.replace},confirmed:!0,confirmationToken:f}));return{needsConfirmation:!0,toolName:"system_create",summary:d.summary,preview:d.preview,args:p}}if(u)return mJ({upload:u.upload,...a.title&&{title:a.title},...a.visibility!==void 0?{visibility:a.visibility}:{},handler:u.handler},o);if(l){let d=await Ws(e,l,a,o);if(d.kind==="handled"||d.kind==="error")return d.result;a=d.createInput}if(!a.content)return{success:!1,error:'URL or upload source creation is supported only for entity types that explicitly handle it. Provide source kind "text" for this entity type, or use system_generate for generated content/artifacts.'};return gJ(e,a,c)},{visibility:"trusted",sideEffects:"writes"})}function _J(e){let t=e.title?` "${e.title}"`:` ${e.entityType}`,n=e.from?.kind==="entity-attachment"?e.from:void 0,o=[`Entity type: ${e.entityType}`,...e.title?[`Title: ${e.title}`]:[],...e.prompt?[`Prompt: ${e.prompt}`]:[],...n?[`Source attachment: ${n.sourceEntityType}/${n.sourceEntityId} (${n.attachmentType})`]:[],...e.targetEntityType&&e.targetEntityId?[`Target: ${e.targetEntityType}/${e.targetEntityId}`]:[]];return{summary:`Generate${t}?`,preview:o.join(`
|
|
184
184
|
`)}}async function SJ(e,t,n){if(!t)return{kind:"ok",sourceAttachment:void 0};let o=await Or(e.entityService,t.sourceEntityType,t.sourceEntityId,e.logger,void 0,n);if(!o.ok)return{kind:"error",result:{success:!1,error:o.error,code:"source-not-found"}};let i={...t,sourceEntityId:o.entity.id};if(!e.attachments.hasProvider(i.sourceEntityType,i.attachmentType))return{kind:"error",result:{success:!1,error:`No attachment provider found for ${i.sourceEntityType}/${i.attachmentType}.`,code:"no-provider"}};let a=e.attachments.getProviderMetadata(i.sourceEntityType,i.attachmentType);if(!a)return{kind:"error",result:{success:!1,error:`Attachment provider for ${i.sourceEntityType}/${i.attachmentType} is missing output metadata.`,code:"provider-missing-metadata"}};return{kind:"ok",sourceAttachment:i,metadata:a}}async function wJ(e,t,n){if(!t)return{kind:"ok",source:void 0};let o=await Or(e.entityService,t.entityType,t.entityId,e.logger,void 0,n);if(!o.ok)return{kind:"error",result:{success:!1,error:o.error,code:"source-not-found"}};return{kind:"ok",source:{...t,entityId:o.entity.id}}}async function xJ(e,t,n){if(!t)return{kind:"ok",target:void 0};let o=await Or(e.entityService,t.entityType,t.entityId,e.logger,void 0,n);if(!o.ok)return{kind:"error",result:{success:!1,error:o.error}};return{kind:"ok",target:{...t,entityId:o.entity.id}}}async function TJ(e,t,n,o,i){let{entityService:a,jobs:s}=e,l=Qr(t.title??n).slice(0,100);if(!l)return{success:!1,error:"Could not derive a slug from the provided title/prompt. Provide a 'title' with at least one URL-safe character."};let c=t.title??l,u=XI(e.entityRegistry,{entityType:t.entityType,id:l,title:c});if(!u)return{success:!1,error:`Entity type '${t.entityType}' does not support queued generation. Provide an exact source to system_create instead.`};let d;try{d=(await a.createEntity({entity:u,options:{deduplicateId:!0,...o?{eventContext:o}:{}}})).entityId}catch(m){return{success:!1,error:Ce(m,"Failed to persist generation stub")}}try{let m=await s.enqueue({type:`${t.entityType}:generation`,data:{entityId:d,prompt:n,...t.title&&{title:t.title},...t.sourceEntityType&&{sourceEntityType:t.sourceEntityType},...t.sourceEntityId&&{sourceEntityId:t.sourceEntityId},...t.sourceEntityIds&&{sourceEntityIds:t.sourceEntityIds},...t.targetEntityType&&{targetEntityType:t.targetEntityType},...t.targetEntityId&&{targetEntityId:t.targetEntityId}},toolContext:i});return{success:!0,data:{entityId:d,status:"generating",jobId:m}}}catch(m){return{success:!1,error:Ce(m,"Failed to queue generation job")}}}async function IJ(e,t,n){let o,i,a=t.kind==="attachment"&&t.replace===!0;if(t.kind==="prompt"||t.kind==="prompt-from-source"){if(e.entityRegistry.getEntityTypeConfig(t.entityType).binaryStorage)return{kind:"error",result:{success:!1,error:`Prompt generation does not support binary entity type '${t.entityType}'. Use operation.kind 'attachment' for source-derived artifacts, or 'standalone-image' or 'cover-image' for generated images.`,code:"unsupported-generation"}};let s=t.kind==="prompt-from-source"?await wJ(e,t.source,n):{kind:"ok",source:void 0};if(s.kind==="error")return s;let l=Wn(t.title);o={entityType:t.entityType,...l?{title:l}:{},prompt:t.prompt,...s.source?.entityType&&{sourceEntityType:s.source.entityType},...s.source?.entityId&&{sourceEntityId:s.source.entityId,sourceEntityIds:[s.source.entityId]}}}else if(t.kind==="standalone-image"){let s=Wn(t.title);o={entityType:"image",...s?{title:s}:{},prompt:t.prompt}}else if(t.kind==="cover-image"){let s=await xJ(e,t.target,n);if(s.kind==="error"){let c=s.result;return{kind:"error",result:"success"in c&&c.success===!1?{...c,code:"target-not-found"}:c}}let l=Wn(t.title);o={entityType:"image",...l?{title:l}:{},prompt:t.prompt,...s.target?.entityType&&{targetEntityType:s.target.entityType},...s.target?.entityId&&{targetEntityId:s.target.entityId}}}else{let s=await SJ(e,{sourceEntityType:t.source.entityType,sourceEntityId:t.source.entityId,attachmentType:t.attachmentType},n);if(s.kind==="error")return s;i=s.sourceAttachment;let l=s.metadata;if(!l||!i)return{kind:"error",result:{success:!1,error:"Attachment generation requires provider metadata.",code:"provider-missing-metadata"}};let c=Wn(t.title);o={entityType:l.outputEntityType,...c?{title:c}:{},from:{kind:"entity-attachment",...i},...a&&{replace:a},...l.targetField&&{targetEntityType:i.sourceEntityType,targetEntityId:i.sourceEntityId}}}return{kind:"ok",createInput:o,sourceAttachment:i}}async function CJ(e,t,n){let o=t.operation,i=Wt(n.userPermissionLevel),a=await IJ(e,o,i);if(a.kind==="error")return a;let{createInput:s,sourceAttachment:l}=a,c=o.kind==="attachment"&&o.replace===!0,u=Jn(e,s.entityType);if(u)return{kind:"error",result:u};let d=Mr(e,s.entityType,"create",n);if(d)return{kind:"error",result:d};let m=e.entityRegistry.getCreateInterceptor(s.entityType);if(!s.prompt&&!s.from)return{kind:"error",result:{success:!1,error:"Provide a generation source."}};if(s.from&&!m)return{kind:"error",result:{success:!1,error:`Entity type '${s.entityType}' does not support attachment-based generation. Use operation.kind prompt-from-source for AI-generated content based on referenced source material, or choose an entity type with an attachment provider.`,code:"unsupported-generation"}};if(!m&&!c){let p=s.prompt?Qr(s.title??s.prompt).slice(0,100):s.title?Qr(s.title):void 0;if(p){if(await e.entityService.getEntity({entityType:s.entityType,id:p}))return{kind:"error",result:{success:!1,error:`A ${s.entityType} already exists for "${p}". To change its fields or status, use system_update; pass replace:true to generate a new copy intentionally.`}}}}return{kind:"ok",prepared:{createInput:s,operation:kJ(o,s,l),sourceAttachment:l,interceptor:m,eventContext:zo(n)}}}function kJ(e,t,n){if(e.kind==="attachment"){let o=n??{sourceEntityType:e.source.entityType,sourceEntityId:e.source.entityId,attachmentType:e.attachmentType};return{kind:"attachment",source:{entityType:o.sourceEntityType,entityId:o.sourceEntityId},attachmentType:o.attachmentType,...t.title&&{title:t.title},...t.replace&&{replace:t.replace}}}if(e.kind==="cover-image")return{kind:"cover-image",target:{entityType:t.targetEntityType??e.target.entityType,entityId:t.targetEntityId??e.target.entityId},...t.title&&{title:t.title},prompt:e.prompt};if(e.kind==="standalone-image")return{kind:"standalone-image",...t.title&&{title:t.title},prompt:e.prompt};if(e.kind==="prompt-from-source")return{kind:"prompt-from-source",entityType:t.entityType,...t.title&&{title:t.title},source:{entityType:t.sourceEntityType??e.source.entityType,entityId:t.sourceEntityId??e.source.entityId},prompt:e.prompt};return{kind:"prompt",entityType:t.entityType,...t.title&&{title:t.title},prompt:e.prompt}}function eC(e){let t=en({label:"generate",requestNoun:"generation"});return jr("generate","Generate durable content or artifacts. Critical: for a request to generate a post/social-post/newsletter/etc. with a cover image, call only the prompt generation first; do not call standalone-image or cover-image until the target entity exists after confirmation. Critical: broad or underspecified topical generation uses operation.kind prompt and has no source field; preserve the user's wording as the prompt and do not stop to ask what details to highlight. Never invent source IDs, use brain-character/profile, uploads, filenames, guessed ids, or placeholders as source refs. Critical: when the user asks to generate from a source such as 'my latest blog post', resolve the source, then call operation.kind prompt-from-source in the same turn; for latest blog/published source requests, use system_list metadata to compare publishedAt and do not rely on semantic search order. If dated candidates such as publishedAt are visible, choose the newest candidate by publishedAt (not updated/created order) and do not stop with prose like 'I found it and can generate it' or 'if that is the one you mean.' Requires confirmation. Calling this tool without confirmed is how you request that confirmation; do not respond with separate prose such as 'I can generate it if you want' or 'I need to queue it first.' Use operation.kind prompt for broad non-image AI-generated entities with no source, including in the same turn after an optional search finds no source. Use operation.kind prompt-from-source only when generating from a resolved existing durable source entity, for example a newsletter from a resolved post: { kind: 'prompt-from-source', entityType: 'newsletter', source: { entityType: 'post', entityId: '...' }, prompt: '...' }. Use standalone-image only for unattached generated images, cover-image with operation.target only for generated covers on existing entities, and attachment with operation.source for source-derived artifacts such as carousel/printable PDFs or OG/social preview images. When a cover-image request for an existing entity resolves a clear target via search/get, call this tool in the same turn; do not stop after saying you found the entity. For regenerate/replace/refresh source-derived artifact requests, call attachment with replace:true immediately; do not say you can queue it later. When the user asks to create/write/draft/generate new durable content, call this tool without confirmed to request confirmation instead of asking for separate prose approval. If you first resolve a clear source entity for the requested generation, still call this tool in the same turn using prompt-from-source. Use system_create instead for saving/importing existing text, URLs, uploads, prior assistant responses, or raw uploaded file preservation with upload transform preserve. On the initial generation request, do not pass confirmed; the tool returns confirmation args.",$I,async(n,o)=>{let i=await CJ(e,n,o);if(i.kind==="error")return i.result;let{createInput:a}=i.prepared,{operation:s,interceptor:l,eventContext:c}=i.prepared;if(n.confirmed){let u=t.validateConfirmed(n.confirmationToken,n);if(u)return u}else{let u=_J(a),d=t.buildArgs((m)=>({operation:s,confirmed:!0,confirmationToken:m}));return{needsConfirmation:!0,toolName:"system_generate",summary:u.summary,preview:u.preview,args:d}}if(l){let u=await Ws(e,l,a,o);if(u.kind==="handled"||u.kind==="error")return u.result;a=u.createInput}if(!a.prompt)return{success:!1,error:"Attachment generation is supported only for entity types that explicitly handle source-derived artifacts."};return TJ(e,a,a.prompt,c,o)},{visibility:"trusted",sideEffects:"writes"})}function tC(e){let{entityService:t,entityRegistry:n,logger:o}=e,i=en({label:"delete",requestNoun:"deletion"});return jr("delete","Request entity deletion by id. Unauthorized callers get a permission error; authorized callers get confirmation first. Do not pass confirmed on the initial request.",FI,async(a,s)=>{if((s.userPermissionLevel??"public")==="public")return{success:!1,error:"Changing content requires higher permission; current permission is Public."};let l=Mr(e,a.entityType,"delete",s);if(l)return l;let c=Jn(e,a.entityType);if(c)return c;if(n.getAdapter(a.entityType).isSingleton===!0)return{success:!1,error:`${a.entityType} is a singleton entity and cannot be deleted through system tools. Update it instead.`};let u=Wt(s.userPermissionLevel),d=await Or(t,a.entityType,a.id,o,void 0,u);if(!d.ok)return{success:!1,error:d.error};let{entity:m}=d;if(a.confirmed){let g=i.validateConfirmed(a.confirmationToken,a);if(g)return g;try{await t.deleteEntity({entityType:a.entityType,id:m.id})}catch(h){return{success:!1,error:Ce(h,"Failed to delete entity")}}return{success:!0,data:{deleted:m.id}}}let p=Hs(m),f=i.buildArgs((g)=>({...a,id:m.id,confirmed:!0,confirmationToken:g}));return{needsConfirmation:!0,toolName:"system_delete",summary:`Delete "${p}"?`,preview:m.content.slice(0,200),args:f}},{visibility:"admin",sideEffects:"writes"})}function rC(e,t){let n=t.map(({oldText:a,newText:s},l)=>{let c=e.indexOf(a);if(!a||c<0)throw Error(`Edit ${l+1}: oldText was not found. Fetch the entity again and provide exact text.`);if(e.indexOf(a,c+1)!==-1)throw Error(`Edit ${l+1}: oldText is ambiguous. Include more surrounding text to match exactly once.`);return{start:c,end:c+a.length,newText:s}}).sort((a,s)=>a.start-s.start),o=0,i=[];for(let a of n){if(a.start<o)throw Error("Edits overlap in the original content. Provide non-overlapping replacements.");i.push(e.slice(o,a.start),a.newText),o=a.end}return i.push(e.slice(o)),i.join("")}import{isDeepStrictEqual as IC}from"util";class Ks{diff(e,t,n={}){let o;if(typeof n==="function")o=n,n={};else if("callback"in n)o=n.callback;let i=this.castInput(e,n),a=this.castInput(t,n),s=this.removeEmpty(this.tokenize(i,n)),l=this.removeEmpty(this.tokenize(a,n));return this.diffWithOptionsObj(s,l,n,o)}diffWithOptionsObj(e,t,n,o){var i;let a=(x)=>{if(x=this.postProcess(x,n),o){setTimeout(function(){o(x)},0);return}else return x},s=t.length,l=e.length,c=1,u=s+l;if(n.maxEditLength!=null)u=Math.min(u,n.maxEditLength);let d=(i=n.timeout)!==null&&i!==void 0?i:1/0,m=Date.now()+d,p=[{oldPos:-1,lastComponent:void 0}],f=this.extractCommon(p[0],t,e,0,n);if(p[0].oldPos+1>=l&&f+1>=s)return a(this.buildValues(p[0].lastComponent,t,e));let g=-1/0,h=1/0,v=()=>{for(let x=Math.max(g,-c);x<=Math.min(h,c);x+=2){let _,y=p[x-1],w=p[x+1];if(y)p[x-1]=void 0;let S=!1;if(w){let I=w.oldPos-x;S=w&&0<=I&&I<s}let C=y&&y.oldPos+1<l;if(!S&&!C){p[x]=void 0;continue}if(!C||S&&y.oldPos<w.oldPos)_=this.addToPath(w,!0,!1,0,n);else _=this.addToPath(y,!1,!0,1,n);if(f=this.extractCommon(_,t,e,x,n),_.oldPos+1>=l&&f+1>=s)return a(this.buildValues(_.lastComponent,t,e))||!0;else{if(p[x]=_,_.oldPos+1>=l)h=Math.min(h,x-1);if(f+1>=s)g=Math.max(g,x+1)}}c++};if(o)(function x(){setTimeout(function(){if(c>u||Date.now()>m)return o(void 0);if(!v())x()},0)})();else while(c<=u&&Date.now()<=m){let x=v();if(x)return x}}addToPath(e,t,n,o,i){let a=e.lastComponent;if(a&&!i.oneChangePerToken&&a.added===t&&a.removed===n)return{oldPos:e.oldPos+o,lastComponent:{count:a.count+1,added:t,removed:n,previousComponent:a.previousComponent}};else return{oldPos:e.oldPos+o,lastComponent:{count:1,added:t,removed:n,previousComponent:a}}}extractCommon(e,t,n,o,i){let a=t.length,s=n.length,l=e.oldPos,c=l-o,u=0;while(c+1<a&&l+1<s&&this.equals(n[l+1],t[c+1],i))if(c++,l++,u++,i.oneChangePerToken)e.lastComponent={count:1,previousComponent:e.lastComponent,added:!1,removed:!1};if(u&&!i.oneChangePerToken)e.lastComponent={count:u,previousComponent:e.lastComponent,added:!1,removed:!1};return e.oldPos=l,c}equals(e,t,n){if(n.comparator)return n.comparator(e,t);else return e===t||!!n.ignoreCase&&e.toLowerCase()===t.toLowerCase()}removeEmpty(e){let t=[];for(let n=0;n<e.length;n++)if(e[n])t.push(e[n]);return t}castInput(e,t){return e}tokenize(e,t){return Array.from(e)}join(e){return e.join("")}postProcess(e,t){return e}get useLongestToken(){return!1}buildValues(e,t,n){let o=[],i;while(e)o.push(e),i=e.previousComponent,delete e.previousComponent,e=i;o.reverse();let a=o.length,s=0,l=0,c=0;for(;s<a;s++){let u=o[s];if(!u.removed){if(!u.added&&this.useLongestToken){let d=t.slice(l,l+u.count);d=d.map(function(m,p){let f=n[c+p];return f.length>m.length?f:m}),u.value=this.join(d)}else u.value=this.join(t.slice(l,l+u.count));if(l+=u.count,!u.added)c+=u.count}else u.value=this.join(n.slice(c,c+u.count)),c+=u.count}return o}}class nC extends Ks{tokenize(e){return e.slice()}join(e){return e}removeEmpty(e){return e}}var oC=new nC;function lp(e,t,n){return oC.diff(e,t,n)}var Qs=r.enum(["png","jpg","jpeg","webp","gif","svg"]),aC=r.enum(["pending","draft","failed"]),sC=r.object({title:r.string().optional(),alt:r.string().optional(),format:Qs,width:r.number(),height:r.number(),status:aC.optional(),processingJobId:r.string().optional(),processingError:r.string().optional(),sourceUrl:r.url().optional(),sourceEntityType:r.string().optional(),sourceEntityId:r.string().optional(),sourceUploadId:r.string().optional(),sourceFilename:r.string().optional(),sourceMediaType:r.string().optional(),attachmentType:r.string().optional(),dedupKey:r.string().optional()}),ra=iC.extend({entityType:r.literal("image"),metadata:sC}),RJ=r.object({url:r.string(),alt:r.string(),title:r.string(),width:r.number(),height:r.number()});function lC(e){return/^https?:\/\//i.test(e)}async function cC(e,t){let n=await fetch(e);if(!n.ok)throw Error(`Failed to fetch: ${n.status} ${n.statusText}`);let o=n.headers.get("content-type");if(t&&!o?.startsWith(t))throw Error(`URL does not point to expected content type: ${o}`);let i=await n.arrayBuffer(),a=Buffer.from(i).toString("base64");return`data:${o?.split(";")[0]??"application/octet-stream"};base64,${a}`}function dC(e){let t=e.trim().match(/^data:image\/([a-z+]+);base64,(.+)$/i);if(!t?.[1]||!t[2])return null;return{format:t[1].toLowerCase(),base64:t[2]}}function Ys(e){let t=dC(e);if(!t)throw Error("Invalid image data URL");return t}function EJ(e,t){return`data:image/${t==="jpg"?"jpeg":t};base64,${e}`}var AJ={png:"iVBORw",jpg:"/9j/",gif:"R0lGOD",webp:"UklGR"};function cp(e){for(let[t,n]of uC(AJ))if(e.startsWith(n))return t;return null}function pC(e){let t=e.toLowerCase(),n=t==="svg+xml"?"svg":t,o=Qs.safeParse(n);return o.success?o.data:null}async function PJ(e){return cC(e,"image/")}function Xs(e){let t=Buffer.from(e,"base64");if(t[0]===137&&t[1]===80&&t[2]===78&&t[3]===71){let n=t.readUInt32BE(16),o=t.readUInt32BE(20);return{width:n,height:o}}if(t[0]===255&&t[1]===216){let n=2;while(n<t.length-8){if(t[n]!==255){n++;continue}let o=t[n+1];if(o===192||o===194){let a=t.readUInt16BE(n+5);return{width:t.readUInt16BE(n+7),height:a}}let i=t.readUInt16BE(n+2);n+=2+i}}if(t[0]===71&&t[1]===73&&t[2]===70){let n=t.readUInt16LE(6),o=t.readUInt16LE(8);return{width:n,height:o}}if(t.length>=30&&t[0]===82&&t[1]===73&&t[2]===70&&t[3]===70){if(t[12]===86&&t[13]===80&&t[14]===56){if(t[15]===32){let n=t[26]??0,o=t[27]??0,i=t[28]??0,a=t[29]??0,s=(n|o<<8)&16383,l=(i|a<<8)&16383;return{width:s,height:l}}if(t[15]===76&&t.length>=25){let n=t.readUInt32LE(21),o=(n&16383)+1,i=(n>>14&16383)+1;return{width:o,height:i}}}}return null}function mC(e){let t=pC(e);if(!t)throw Error(`Unsupported image format: ${e}`);return t}class up{entityType="image";purpose="Image assets such as generated covers, social previews, and uploaded images.";schema=ra;toMarkdown(e){return e.content}fromMarkdown(e){let{format:t,base64:n}=Ys(e),o=Xs(n);return{entityType:"image",content:e,metadata:{format:mC(t),width:o?.width??0,height:o?.height??0}}}extractMetadata(e){return e.metadata}parseFrontMatter(e,t){return t.parse({})}generateFrontMatter(e){return""}getBodyTemplate(){return""}createImageEntity(e){let{dataUrl:t,title:n,alt:o}=e,{format:i,base64:a}=Ys(t),s=Xs(a),c=cp(a)??mC(i);return{entityType:"image",content:t,metadata:{title:n,alt:o??n,format:c,width:s?.width??0,height:s?.height??0,...e.status&&{status:e.status},...e.sourceUrl&&{sourceUrl:e.sourceUrl},...e.sourceEntityType&&{sourceEntityType:e.sourceEntityType},...e.sourceEntityId&&{sourceEntityId:e.sourceEntityId},...e.sourceUploadId&&{sourceUploadId:e.sourceUploadId},...e.sourceFilename&&{sourceFilename:e.sourceFilename},...e.sourceMediaType&&{sourceMediaType:e.sourceMediaType},...e.attachmentType&&{attachmentType:e.attachmentType},...e.dedupKey&&{dedupKey:e.dedupKey}}}}}var MJ=new up;function xre(e){return fC(e,{skipInvalid:!0,noRefs:!0,sortKeys:!0})}function hC(e){return gC(e)}var jJ=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/,OJ=r.record(r.string(),r.unknown());async function yC(e,t){let n=await t.getEntity({entityType:"image",id:e},ra);if(!n)return;return{url:n.content,alt:n.metadata.alt??"",title:n.metadata.title??"",width:n.metadata.width,height:n.metadata.height}}function vC(e,t){let n=jJ.exec(e.content);if(!n?.[1])return;try{let o=OJ.safeParse(hC(n[1]));if(o.success){let i=o.data[t];return typeof i==="string"?i:void 0}}catch{return}return}function bC(e){return vC(e,"coverImageId")}function NJ(e){return vC(e,"ogImageId")}function dp(e,t){return{...e,content:na(e.content,"coverImageId",t)}}function pp(e,t){return{...e,content:na(e.content,"ogImageId",t)}}async function DJ(e,t){let n=bC(e);if(!n)return;return yC(n,t)}var mp=_C();function zJ(e,t){let n=mp.parse(e),o=new Map;el(n,"definition",(a)=>{if(!o.has(a.identifier))o.set(a.identifier,a)});let i=new Set;return el(n,(a,s,l)=>{if(a.type!=="image"&&a.type!=="imageReference")return;let c=a.type==="image"?a:o.get(a.identifier);if(!c)return;let u=t(c.url);if(u===c.url)return;if(i.add(c.url),a.type==="image")a.url=u;else if(l&&s!==void 0)l.children[s]={type:"image",url:u,alt:a.alt,title:c.title}}),i.size>0?mp.stringify(n):e}function UJ(e){let t=[],n=mp.parse(e);return el(n,"image",(o)=>{t.push({url:o.url,alt:o.alt??"",title:o.title??void 0})}),t}var SC=400;function tl(e,t,n){if(n===null)return!Object.hasOwn(e,t);return Object.hasOwn(e,t)&&IC(e[t],n)}function fp(e,t){return new Set([...t.getFrontmatterExtensions(e).flatMap((n)=>Object.keys(n.shape)),...t.getGroupings().filter((n)=>n.types.includes(e)).map((n)=>n.field)])}function qJ(e,t,n){if(n.has(t))return gp(e.content).frontmatter[t];return t==="visibility"?e.visibility:e.metadata[t]}function CC(e,t,n){let{visibility:o,coverImageId:i,ogImageId:a,...s}=t,l=o===void 0?e.visibility:xC.parse(o),c=Object.hasOwn(t,"coverImageId")?dp(e,typeof i==="string"?i:null):e,u=Object.hasOwn(t,"ogImageId")?pp(c,typeof a==="string"?a:null):c,d={...e.metadata};for(let[g,h]of Object.entries(s))if(h===null)delete d[g];else d[g]=h;let m={...u,visibility:l,metadata:d};for(let[g,h]of Object.entries(s))if(h===null)delete m[g];else m[g]=h;let p=fp(e.entityType,n),f=!1;for(let[g,h]of Object.entries(t)){if(!p.has(g))continue;m.content=na(m.content,g,h),f=!0}if(f)m.metadata=n.projectMetadata(e.entityType,m.content,d);return m}function LJ(e,t,n){let o=n.getAdapter(e.entityType),i=o.fromMarkdown(e.content),a=o.fromMarkdown(t),s={...e.metadata};for(let l of new Set([...Object.keys(i.metadata??{}),...Object.keys(a.metadata??{})])){let c=a.metadata?.[l];if(IC(i.metadata?.[l],c))continue;if(c===void 0)delete s[l];else s[l]=c}return{...e,...a,id:e.id,entityType:e.entityType,created:e.created,updated:e.updated,contentHash:e.contentHash,content:t,metadata:s,visibility:Zs(t)??e.visibility}}var $J=new Set(["visibility","coverImageId","ogImageId"]),FJ=r.record(r.string(),r.unknown());function BJ(e,t,n,o){let i=t.fields;if(!i)return;let a=n.getEffectiveFrontmatterSchema(e.entityType);if(!a)return;let s=fp(e.entityType,n),l=Object.keys(i).filter((g)=>s.has(g)),c;try{if(c=CC(e,i,n),l.length>0){let g=n.validateEntity(e.entityType,c),h=o.serializeEntity(g),v=gp(h).frontmatter,x=o.deserializeEntity(h,e.entityType).metadata??{};for(let _ of l){let y=i[_];if(!tl(v,_,y)||!tl(x,_,y))return{success:!1,error:`The requested ${_} value would not survive frontmatter persistence.`}}}}catch(g){return{success:!1,error:Ce(g,"Invalid field update")}}let u=Object.keys(i).filter((g)=>!s.has(g)&&!$J.has(g)&&(g in a.shape));if(u.length===0)return;let d=n.getAdapter(e.entityType),m;try{c=n.validateEntity(e.entityType,c),m=d.extractMetadata(c)}catch{return}let p=[],f=[];for(let g of u){let h=i[g];if(Object.hasOwn(m,g)){if(!tl(m,g,h))p.push(g)}else if(h!==null||!Object.hasOwn(e.metadata,g))f.push(g)}if(f.length>0){let g;try{g=d.parseFrontMatter(d.toMarkdown(c),FJ)}catch{if(p.length===0)return}if(g){for(let h of f)if(!tl(g,h,i[h]))p.push(h)}}if(p.length===0)return;return{success:!1,error:`${e.entityType} does not persist ${p.join(", ")} through 'fields'. The update would report success without changing anything. Provide full markdown with frontmatter via 'content' instead.`}}var wC=/^---\r?\n(?:[\s\S]*?\r?\n)?---[ \t]*(?:\r?\n|$)/;function kC(e,t,n){let o=wC.exec(e.content)?.[0];if(o===void 0||!t.trim()||wC.test(t))return t;if(n.getAdapter(e.entityType).hasBody===!1)return{success:!1,error:`${e.entityType} has no body. Replace its full markdown, including frontmatter.`};return o+t}function GJ(e,t,n){if(t.content===void 0)return;let o=t.content.trim(),i=n.getEffectiveFrontmatterSchema(e);if(!i)return;if(!o)return{success:!1,error:"Full content replacement cannot be empty for this entity type. Use 'fields' for partial updates."};try{n.getAdapter(e).parseFrontMatter(t.content,i)}catch{return{success:!1,error:"Invalid content replacement for this entity type. Provide full markdown with valid frontmatter, or use 'fields' for partial updates."}}return}function JJ(e,t,n){if(!t.fields||!("coverImageId"in t.fields))return;let o=t.fields.coverImageId;if(o!==null&&o!==void 0&&typeof o!=="string")return{success:!1,error:"coverImageId must be a string or null"};if(o==="__PENDING__"||typeof o==="string"&&o.startsWith("upload-"))return{success:!1,error:"coverImageId must reference an existing image id or be null"};if(n.getAdapter(e).supportsCoverImage)return;return{success:!1,error:`Entity type '${e}' doesn't support cover images`}}function WJ(e,t,n){if(t.fields&&"status"in t.fields)return t.fields.status;if(t.content!==void 0){let o=n.getEffectiveFrontmatterSchema(e.entityType);if(!o)return e.metadata.status;try{return n.getAdapter(e.entityType).parseFrontMatter(t.content,o).status}catch{return e.metadata.status}}return e.metadata.status}function RC(e,t,n){let o=fp(e.entityType,n);if(t.fields)return Object.entries(t.fields).map(([l,c])=>{let u=qJ(e,l,o);if(!o.has(l))return`${l}: ${String(u??"(empty)")} \u2192 ${String(c)}`;let d=n.getEffectiveFrontmatterSchema(e.entityType)?.shape[l],m=d!==void 0&&r.safeParse(d,u).success,p=u===void 0?"(absent)":`${JSON.stringify(u)}${m?"":" (invalid existing value)"}`,f=c===null?"(removed)":JSON.stringify(c);return`${l}: ${p} \u2192 ${f}`}).join(`
|
|
@@ -187,9 +187,9 @@ ${GS}`:""),tools:w,activeTools:y,...i!==void 0&&c.supportsTemperature&&{temperat
|
|
|
187
187
|
`),s=lp(i,a,{maxEditLength:SC});if(!s)return`Full content replacement (line diff omitted: more than ${SC} changed lines).`;return s.filter((l)=>l.added||l.removed).flatMap((l)=>l.value.map((c)=>`${l.added?"+":"-"} ${c}`)).join(`
|
|
188
188
|
`)}function EC(e,t,n,o){return BJ(e,t,n,o)??GJ(e.entityType,t,n)??JJ(e.entityType,t,n)}function AC(e,t,n){return TC(e.entityType,e.metadata.status,WJ(e,t,n),n)==="non-publish"?"update":"publish"}function PC(e,t,n){return t.content!==void 0?LJ(e,t.content,n):CC(e,t.fields??{},n)}function bn(e){return{success:!1,error:e}}async function HJ(e,t,n,o){if([t.fields,t.content,t.edits,t.source].filter((c)=>c!==void 0).length>1)return bn("Provide only one of 'fields', 'content', 'edits', or 'source'.");if(t.confirmed&&t.contentHash&&n.contentHash!==t.contentHash)return bn("Entity was modified since you reviewed the changes. Please try again.");if(t.edits!==void 0)return{operation:{content:rC(n.content,t.edits)}};let a,s;if(t.source!==void 0){let c=await Gs(e,t.source,o);if(!c.success)return c;a=Js(t.source,c),s={content:c.content}}else s=VI({...t.fields!==void 0?{fields:t.fields}:{},...t.content!==void 0?{content:t.content}:{}});if(s.content===void 0)return s.fields?{operation:s}:bn("Provide 'content' (full replacement) or 'fields' (partial update)");let l=kC(n,s.content,e.entityRegistry);if(typeof l!=="string")return l;return{operation:{content:l},...a?{source:a}:{}}}function MC(e){let{entityService:t,logger:n,entityRegistry:o}=e,i=en({label:"update",requestNoun:"the update"}),a=(c,u)=>{if(!c.confirmed||!c.confirmationToken||c.edits!==void 0||c.fields!==void 0||c.source!==void 0||c.content?.trim())return{input:c,replayed:!1};let d=ap.safeParse(i.takePending(c.confirmationToken));if(!d.success||d.data.entityType!==u.entityType||d.data.id!==u.id)return bn("No pending update confirmation found for this entity. Please request the update again.");return{input:d.data,replayed:!0}},s=async(c,u,d,m,p)=>{if(!m){let g=i.validateConfirmed(c.confirmationToken,c);if(g)return g}let f=PC(u,d,o);if(f.visibility!==u.visibility&&!Vs(p.userPermissionLevel,f.visibility))return bn(`Cannot set entity visibility to "${f.visibility}" \u2014 caller permission "${p.userPermissionLevel??"public"}" is not allowed to write at that level.`);try{let g=zo(p);if((await t.updateEntity({entity:f,options:{expectedContentHash:u.contentHash,...g?{eventContext:g}:{}}})).skipReason==="content-conflict")return bn("Entity was modified before the update could be saved. Please request and confirm the update again.")}catch(g){return bn(Ce(g,"Failed to update entity"))}return{success:!0,data:{updated:u.id}}},l=(c,u,{operation:d,source:m})=>{let{fields:p,content:f,source:g,...h}=c;return{needsConfirmation:!0,toolName:"system_update",summary:`Update "${Hs(u)}"?`,completionSummary:`Updated ${ZI(u.entityType)}.`,preview:RC(u,d,o),args:i.buildArgs((v)=>({...h,...c.edits!==void 0?{edits:c.edits}:m?{source:m}:d,id:u.id,confirmed:!0,confirmationToken:v,contentHash:u.contentHash}))}};return jr("update","Update an entity's fields or content. For small content changes, fetch the entity and use edits with exact oldText/newText pairs instead of regenerating the whole document. For a large rewrite whose text the user supplied, use source with exact user-message boundaries instead of copying it into content. Use only one of fields, content, edits, or source. Requires confirmation; call this tool without confirmed to request that confirmation instead of asking for plain-text approval. For direct requests that provide exact IDs to set an existing image as an entity cover, call this tool on the target entity with fields.coverImageId set to the image ID; do not stop after lookup.",ap,async(c,u)=>{let d=await Or(t,c.entityType,c.id,n,void 0,Wt(u.userPermissionLevel));if(!d.ok)return bn(d.error);let{entity:m}=d,p=a(c,m);if("success"in p)return p;let{input:f,replayed:g}=p,h=await HJ(e,f,m,u);if("success"in h)return h;let{operation:v}=h,x=EC(m,v,o,t);if(x)return x;let _=Mr(e,f.entityType,AC(m,v,o),u);if(_)return _;return f.confirmed?s(f,m,v,g,u):l(f,m,h)},{visibility:"trusted",sideEffects:"writes"})}function jC(e){return[YI(e),eC(e),tC(e),MC(e)]}function rl(e){if(e.interfaceType!==ct)return;if(e.userPermissionLevel!=="public"||e.isAnchor)throw Error("Guest execution denied")}var VJ=0.5,hp=(e)=>e==="public"?{publishedOnly:!0}:{};function ZJ(e,t){if(e.length===0)return;let n=Math.round(Math.max(...e.map((o)=>o.score))*100)/100;return{minScore:t,weakerMatches:e.length,bestScore:n,hint:`No result reached minScore ${t}, but ${e.length} weaker match${e.length===1?"":"es"} exist (best score ${n}). Broad or abstract questions match content weakly: search again with a lower minScore, such as 0.3, before concluding that nothing relevant exists.`}}function OC(e){let{entityService:t,logger:n}=e;return[_n("system","search","Search entities using semantic search. For broad search, make one system_search call with scope.kind all. Use scope.kind type only when the user asks for a specific entity type. Applies a default minScore of 0.5 to reduce weak matches; lower minScore only for exploratory or loose recall. An empty result with belowThreshold means weaker matches exist: search again with a lower minScore before concluding that nothing relevant exists. Search results include each matched entity's content. When relevant results already contain the complete evidence needed, answer from those results instead of redundantly listing or getting the same entities. Search results are candidates; do not present weak or unrelated candidates as exact matches.",DI,async(o,i)=>{rl(i);let a=Wt(i.userPermissionLevel),s=o.minScore??VJ,l=await t.search({query:o.query,options:{limit:o.limit??e.searchLimit,...o.scope.kind==="type"&&{types:[o.scope.entityType]},...o.includeUngenerated!==void 0&&{includeUngenerated:o.includeUngenerated},visibilityScope:a,...hp(a)}}),c=l.filter((d)=>d.score>=s),u=c.length===0?ZJ(l,s):void 0;return{success:!0,data:{results:c.map((d)=>{let m=sp(d.entity,e.entityRegistry);return{...d,entity:m,...m!==d.entity?{excerpt:m.content}:{}}}),...u&&{belowThreshold:u}}}},{visibility:"public",sideEffects:"none",cli:{name:"search"}}),_n("system","get","Retrieve a specific entity by type and identifier (ID, slug, or title). If retrieval fails, report the entity as not found rather than describing related generation work as pending.",zI,async(o,i)=>{if(rl(i),!t.getEntityTypes().includes(o.entityType))return{success:!1,error:`Unknown entity type: ${o.entityType}. Available: ${t.getEntityTypes().join(", ")}`};let a=Wt(i.userPermissionLevel),s=await Or(t,o.entityType,o.id,n,void 0,a,hp(a));if(!s.ok)return{success:!1,error:s.error};return{success:!0,data:{entity:sp(s.entity,e.entityRegistry)}}},{visibility:"public",sideEffects:"none",cli:{name:"get"}}),_n("system","list","List entities by a known entity type. Returns metadata only \u2014 use system_get for full content. Use system_search, not system_list, for broad or vague lookup requests. Use system_list to inspect metadata dates such as publishedAt when the user asks for the latest item of a known type, such as latest blog post.",UI,async(o,i)=>{if(rl(i),!t.getEntityTypes().includes(o.entityType))return{success:!1,error:`Unknown entity type: ${o.entityType}. Available: ${t.getEntityTypes().join(", ")}`};let a=Wt(i.userPermissionLevel),s={visibilityScope:a};if(o.status&&o.status!=="any")s.metadata={status:o.status};let{defaultSort:l}=e.entityRegistry.getEntityTypeConfig(o.entityType),u=(await t.listEntities({entityType:o.entityType,options:{limit:o.limit??20,filter:s,...hp(a),...l?{sortFields:l}:{}}})).map(({content:d,contentHash:m,...p})=>p);return{success:!0,data:{entities:u,count:u.length}}},{visibility:"public",sideEffects:"none",cli:{name:"list"}})]}function NC(e){let{entityService:t}=e;return[_n("system","insights",`Get aggregate content insights and analytics only. For a general overview of actual content, use system_list instead. Available types: ${e.insights.getTypes().join(", ")}.`,GI,async(n,o)=>{let i=Wt(o.userPermissionLevel);return{success:!0,data:await e.insights.get(n.type,t,i)}},{visibility:"public",sideEffects:"none"})]}function DC(e){let{jobs:t}=e;return[jr("job_status","Inspect runtime job status for ready checks only when the prior operation created a job, or for status disputes. With a known batch ID, pass batchId. Without an ID, call this tool with no arguments to list active jobs and batches; do not ask the user for an ID first. Do not argue from the transcript alone.",BI,async(n)=>{if(n.batchId){let a=await t.getBatchStatus(n.batchId);if(!a)return{success:!1,error:`No batch found with ID: ${n.batchId}`};let s=a.totalOperations>0?Math.round(a.completedOperations/a.totalOperations*100):0;return{success:!0,data:{batchId:n.batchId,status:a.status,progress:{total:a.totalOperations,completed:a.completedOperations,failed:a.failedOperations,percentComplete:s},currentOperation:a.currentOperation,errors:a.errors}}}let o=await t.getActiveJobs(n.jobTypes),i=await t.getActiveBatches();return{success:!0,data:{summary:{activeJobs:o.length,activeBatches:i.length},jobs:o.map((a)=>({id:a.id,type:a.type,status:a.status,priority:a.priority,retryCount:a.retryCount,createdAt:new Date(a.createdAt).toISOString(),startedAt:a.startedAt?new Date(a.startedAt).toISOString():null})),batches:i.map((a)=>({batchId:a.batchId,status:a.status.status,totalOperations:a.status.totalOperations,completedOperations:a.status.completedOperations,failedOperations:a.status.failedOperations,currentOperation:a.status.currentOperation,pluginId:a.metadata.metadata.pluginId,errors:a.status.errors}))}}},{visibility:"public",sideEffects:"none"})]}function KJ(e){let{entityCounts:t,daemons:n,endpoints:o,interactions:i,...a}=e;return a}function zC(e){return[_n("system","status","Get system status including model, version, interfaces, and tools",r.object({}),async()=>({success:!0,data:KJ(await e.getAppInfo())}),{visibility:"public",sideEffects:"none",cli:{name:"status"}})]}function UC(e){return[...OC(e),...DC(e),...zC(e),...jC(e),...NC(e)]}function qC(e){return[{uri:"entity://types",name:"Entity Types",description:"List of registered entity types",mimeType:"text/plain",handler:async()=>({contents:[{uri:"entity://types",mimeType:"text/plain",text:e.entityService.getEntityTypes().join(`
|
|
189
189
|
`)}]})},{uri:"brain://identity",name:"Brain Identity",description:"Brain character \u2014 name, role, purpose, values",mimeType:"application/json",handler:async()=>({contents:[{uri:"brain://identity",mimeType:"application/json",text:JSON.stringify(e.getIdentity(),null,2)}]})},{uri:"brain://profile",name:"Anchor Profile",description:"Brain owner profile \u2014 name, bio, expertise",mimeType:"application/json",handler:async()=>({contents:[{uri:"brain://profile",mimeType:"application/json",text:JSON.stringify(e.getProfile(),null,2)}]})},{uri:"brain://status",name:"Brain Status",description:"System status \u2014 version, model, interfaces, tools",mimeType:"application/json",handler:async()=>({contents:[{uri:"brain://status",mimeType:"application/json",text:JSON.stringify(await e.getAppInfo(),null,2)}]})}]}function LC(e){let{entityService:t}=e;return[{name:"entity-list",uriTemplate:"entity://{type}",description:"List entities of a given type",mimeType:"application/json",list:async()=>t.getEntityTypes().map((o)=>({uri:`entity://${o}`,name:`${o} entities`})),complete:{type:async()=>t.getEntityTypes()},handler:async({type:n})=>{let o=t.getEntityTypes();if(!o.includes(n))throw Error(`Unknown entity type: ${n}. Available: ${o.join(", ")}`);let a=(await t.listEntities({entityType:n})).map((s)=>({id:s.id,entityType:s.entityType,...s.metadata,updated:s.updated}));return{contents:[{uri:`entity://${n}`,mimeType:"application/json",text:JSON.stringify(a,null,2)}]}}},{name:"entity-detail",uriTemplate:"entity://{type}/{id}",description:"Read a single entity by type and ID",mimeType:"text/markdown",complete:{type:async(n)=>{let o=t.getEntityTypes();return n?o.filter((i)=>i.startsWith(n)):o},id:async()=>[]},handler:async({type:n,id:o})=>{let i=await t.getEntity({entityType:n,id:o});if(!i)throw Error(`Entity not found: ${n}/${o}`);return{contents:[{uri:`entity://${n}/${o}`,mimeType:"text/markdown",text:i.content}]}}}]}function $C(e){return[{name:"create",description:"Create new content of any type",args:{type:{description:"Entity type (e.g. post, deck, note)",required:!0},topic:{description:"Topic or title for the content"}},handler:async({topic:n,type:o})=>({messages:[{role:"user",content:{type:"text",text:n?`Create a new ${o} about: ${n}`:`Create a new ${o}. Ask me what it should be about.`}}]})},{name:"generate",description:"AI-generate content with a prompt",args:{type:{description:`Entity type (${(()=>e.entityService.getEntityTypes().join(", "))()})`,required:!0},topic:{description:"What to generate",required:!0}},handler:async({type:n,topic:o})=>({messages:[{role:"user",content:{type:"text",text:`Generate a ${n} about: ${o}`}}]})},{name:"review",description:"Review and improve existing content",args:{type:{description:"Entity type",required:!0},id:{description:"Entity ID or slug",required:!0}},handler:async({type:n,id:o})=>({messages:[{role:"user",content:{type:"text",text:`Review my ${n} "${o}". Read it first, then give me specific feedback on structure, clarity, and impact. Suggest concrete improvements.`}}]})},{name:"publish",description:"Publish content \u2014 preview, confirm, and publish",args:{type:{description:"Entity type",required:!0},id:{description:"Entity ID or slug",required:!0}},handler:async({type:n,id:o})=>({messages:[{role:"user",content:{type:"text",text:`I want to publish my ${n} "${o}". Show me a preview first, then publish it.`}}]})},{name:"brainstorm",description:"Brainstorm ideas using brain context and expertise",args:{topic:{description:"Topic to brainstorm about",required:!0}},handler:async({topic:n})=>({messages:[{role:"user",content:{type:"text",text:`Let's brainstorm about: ${n}. Use my existing content and expertise as context. Give me fresh angles and concrete ideas.`}}]})}]}function FC(e){let t=e.entityService.getEntityTypes(),n=t.map((o)=>`- ${o}: ${e.entityRegistry.getAdapter(o).purpose}`);return["## Entity CRUD","","Use these system tools for ALL entity operations:","","Treat explicit verbs such as save, create, capture, remember, import, add/connect an agent, approve/archive an agent, update, delete, generate, publish, or sync as mutation requests. Entity-specific instructions may require proactively recording the user's request itself for demand or workflow tracking; follow those instructions even when the user did not use a separate save/create verb. Ordinary status questions like 'what is the status', 'is it ready', 'did that finish', or 'what happened' are not capture requests; answer them by using the relevant status/read tool for the prior operation. Never call system_create for a status follow-up.","",`- **system_create**: Create an entity from existing/concrete material. Requires confirmation before persisting; call system_create without \`confirmed\` to request that confirmation, and never pass \`confirmed: true\` on the initial user request. Use the typed \`visibility\` field instead of rewriting exact source text: omit it for public content, use \`shared\` for team/collaborator content, and use \`restricted\` for private/admin-only content. Public callers may write only public content, Trusted callers public or shared, and Admin callers all three levels. If the user only says 'not public' without clarifying team/shared versus private/admin-only, ask which scope they mean. Required \`source\` union: \`{ kind: "text", content }\` stores exact/direct content; \`{ kind: "url", url }\` creates URL/domain-backed records such as links (preserve bare domains as bare domains); \`{ kind: "upload", upload, transform: "extract-markdown" }\` imports extractable upload bytes as a markdown note; \`{ kind: "upload", upload, transform: "preserve" }\` preserves raw uploaded bytes as their durable file entity; \`{ kind: "prior-response", messageId? }\` saves a previous assistant answer/summary by reference without copying or paraphrasing it. If a direct save request includes the content in the same message, that content is sufficient, even if it is a short sentence or fragment after a colon or embedded in the request phrase (for example, "Save this memo about the launch timeline"); call system_create instead of asking the user to paste it again. If the immediate context is an assistant summary/answer about an upload and the user asks to save it/that/this/summary, create a note with \`source.kind: "prior-response"\`; do this even when the prior answer says there was limited readable content. Do not ask whether they meant the summary or the file after you just summarized/answered about the upload: save the visible prior response as a note. Do not treat a bare upload receipt like "I got filename. What would you like me to do?" as a summary/answer; if the user then says "save it", preserve the latest uploaded file itself with upload \`preserve\` (image uploads as entityType image, PDFs/documents as their file entity type). Only use \`source.kind: "upload"\` when the runtime supplies an actual upload reference/attachment; if the message contains a pasted uploaded-file transcript with readable content (for example, \`User uploaded a file "name.md": ...\`), save the visible transcript content as \`source.kind: "text"\`. Only use upload \`preserve\` otherwise when they explicitly want to save the uploaded file/document itself. Use system_generate, not system_create, for AI generation, generated images, cover images, and source-derived artifacts. Available entity types: ${t.join(", ")}.`,'- **system_generate**: Generate a new durable entity or deterministic artifact. Requires confirmation before queueing generation; call system_generate without `confirmed` to request that confirmation, and never pass `confirmed: true` on the initial user request. When the user asks you to create, write, draft, or generate new durable content and has not supplied final exact content to store, call system_generate instead of drafting the content in chat or asking for separate prose approval first. An underspecified generation request still supplies a usable prompt: preserve the user\'s wording and call system_generate rather than stopping to ask what details to highlight. If generation depends on an existing source entity (for example, a newsletter from a blog post), resolve the source with read/search/list tools first unless the user gives an exact entity id in quotes, then call system_generate with `operation.kind: "prompt-from-source"` in the same turn when a clear source is found. If you identify the latest source entity, do not stop after saying you found it or can generate from it; call system_generate immediately. If no existing durable source entity is resolved, use `operation.kind: "prompt"` in the same turn, including after an optional search returns no source; never invent source IDs, use upload IDs/filenames as entity refs, use profile/brain-character as a generic source, or create placeholder source refs. For broad topical prompts like \'about AI\' or \'about continuous learning\', use `operation.kind: "prompt"`. If the user asks for the latest published/blog source, use system_list for that entity type (for blog posts, entityType post) to inspect publishedAt dates; do not rely on semantic search result order. Choose the newest matching candidate by publishedAt (not updated/created order) and proceed with system_generate rather than asking for separate prose approval; do not say \'if that is the one you mean\' when a newest dated candidate is visible. Do not say \'I can generate it if you want\' or \'I need to queue it first\'; calling system_generate without `confirmed` is the confirmation request. Required `operation` union: `{ kind: "prompt", entityType, prompt }` generates a new non-image durable entity from a broad prompt with no source; `{ kind: "prompt-from-source", entityType, source: { entityType, entityId }, prompt }` generates from an existing resolved entity, such as a newsletter from a blog post. `{ kind: "standalone-image", prompt }` generates an unattached image; `{ kind: "cover-image", target: { entityType, entityId }, prompt }` generates an image and attaches it to an existing canonical entity as `coverImageId`; `{ kind: "attachment", source: { entityType, entityId }, attachmentType }` renders a deterministic artifact from an existing entity attachment provider. For save/render/regenerate/replace requests for source-derived artifacts, call `system_generate` with `operation.kind: "attachment"` immediately; do not say you can queue it later. Use `replace: true` when the user says regenerate, replace, refresh, or update an existing artifact. For OG/social preview renders, use `attachmentType: "og-image"`; the provider derives the output image and updates `ogImageId`. For deck carousel PDFs use `attachmentType: "carousel"`; for printable post/project PDFs use `attachmentType: "printable"`. If the user asks to attach a generated artifact to another entity, generate the artifact first in the same turn; do not ask whether they mean an existing artifact when the source entity is explicit or given as a quoted id such as deck `distributed-systems-primer`. Update the target only after the real artifact ID exists. To create an entity and a cover image, first create/generate only the entity, then after confirmation and after the real canonical entity ID is known call system_generate with operation.kind cover-image. When the user asks to create/regenerate a cover for an existing entity and search/get resolves a clear target, call system_generate with operation.kind cover-image in the same turn; do not stop after saying you found it. In a single initial request for \'a post with a cover image\', do not also call standalone-image; never guess a future target ID, and do not generate a standalone image as a substitute for a requested cover image.','- **system_update**: Modify an entity\'s fields or content. Use `edits` for small content changes: fetch the entity, then send exact oldText/newText pairs, with each oldText matching once in the original Markdown. Put multiple non-overlapping edits in one call. Do not regenerate the whole note for a small change; omit `content` and `fields` when using `edits`. Never replace unchanged content with placeholders or ellipses. For a whole-document rewrite, when the user supplies the replacement text, use `source: { kind: "user-message", startAfter, endBefore }` with exact unique boundaries (`boundaryMode: "lines"` for delimiter lines) so the server reads it verbatim; never copy pasted text into `content` or long `edits`. Use full `content` only for whole-document replacements you write yourself. Text without frontmatter replaces the body and keeps the stored frontmatter; text with frontmatter replaces the whole document. Use only one of `fields`, `content`, `edits`, or `source`. Use `fields` for title, status, coverImageId, ogImageId, and other frontmatter/metadata changes. To remove or clear a cover image, set `fields.coverImageId` to null, not an empty string. Use system_update for coverImageId when an existing image entity id is known; if the user says to set an existing image as a cover, update `coverImageId` even when `ogImageId` already points at that image. To generate a new cover image for an existing entity, use system_generate with operation.kind cover-image. Cover images use `coverImageId`; OG/social previews use `ogImageId`; do not treat them as interchangeable. Requires confirmation before applying changes; call system_update without `confirmed` to request that confirmation, rather than asking for prose approval. For explicit publish requests, use the publishing tool if available instead of changing status with system_update; follow-up pronouns like \'publish it\' should target the entity just read or updated in the conversation.',"- **system_delete**: Admin-only entity removal. Requires confirmation before deleting. Never pass `confirmed: true` on the initial user request; call without `confirmed` so the confirmation flow can ask an administrator first. If system_delete is not available in the current tool surface, say deletion requires Admin access; do not imply a confirmation flow is available. Protected identity/profile records such as brain-character and anchor-profile cannot be deleted; update them instead.","- **system_get**: Retrieve a specific entity by type and ID/slug/title.","- **system_list**: List entities by type with optional filters. For simple list/show-all/summary requests that name or browse a known type or synonym (for example essays/articles/blog posts => post), use system_list with that entity type instead of semantic search. For 'summarize my blog posts' or similar whole-type summaries, first call system_list for entityType post, then summarize those returned entities. For 'latest' requests, use system_list metadata dates such as publishedAt to choose the newest candidate.","- **system_search**: Semantic search across all entities. Search results include matched entity content; when relevant results already provide the complete evidence needed, answer from them instead of redundantly calling system_list or system_get for those same entities. For each new user question about what they have written, mentioned, discussed, or saved, run a fresh search for that turn instead of answering from prior-turn search results or memory; this includes analysis phrasing such as 'How do I discuss X in my writing?' even if prior turns searched related topics.","","Do not ask for prose confirmation instead of calling the applicable mutating tool; for create, update, delete, generate, publish, sync, and similar state-changing requests, the initial tool call without `confirmed` is how you create the pending confirmation. Never claim a durable create/update/delete change was saved, created, done, or completed unless the relevant tool call succeeded or returned a pending confirmation. If a create/update/delete tool is unavailable, unauthorized, or intentionally not called, say you can't make that durable change from the current context; never say saved/created/done. For an explicit write request from an unauthorized/currently unwritable context, refuse directly; do not call system_status or system_search to check permission or look up related content. Entity type descriptions may mark projection-owned or system-maintained types read-only; refuse mutation requests for those types directly without calling read or write tools, searching for a target, or asking which record to mutate.","","Entity types \u2014 select `entityType` by what the type is for:",...n].join(`
|
|
190
|
-
`)}var Uo="system",QJ=r.object({toolName:r.string(),args:r.unknown(),...GC.partial().shape});function nl(e,t,n,o,i){for(let a of e)try{t(a)}catch{i.debug(`System ${o} ${n(a)} already registered, skipping`)}}function JC(e,t,n,o){let i=UC(e);nl(i,(d)=>t.registerTool(Uo,d),(d)=>d.name,"tool",o);let a=n.subscribe(BC.toolExecute(Uo),async(d)=>{let m=QJ.safeParse(d.payload);if(!m.success)return{success:!1,error:"Invalid system tool execute payload"};let{toolName:p,args:f,interfaceType:g,actor:h,conversationId:v,channelId:x,userPermissionLevel:_}=m.data,y=i.find((C)=>C.name===p);if(!y)return{success:!1,error:`System tool not found: ${p}`};let w={interfaceType:g??"system",actor:h??{kind:"service",serviceId:"system"}};if(v)w.conversationId=v;if(x)w.channelId=x;if(_)w.userPermissionLevel=_;return{success:!0,data:await y.handler(f,w)}});o.debug(`Registered ${i.length} system tools`);let s=qC(e);nl(s,(d)=>t.registerResource(Uo,d),(d)=>d.uri,"resource",o),o.debug(`Registered ${s.length} system resources`);let l=LC(e);nl(l,(d)=>t.registerResourceTemplate(Uo,d),(d)=>d.uriTemplate,"resource template",o),o.debug(`Registered ${l.length} system resource templates`);let c=$C(e);nl(c,(d)=>t.registerPrompt(Uo,d),(d)=>d.name,"prompt",o),o.debug(`Registered ${c.length} system prompts`);let u=FC(e);try{t.registerInstructions(Uo,u)}catch{o.debug("System instructions already registered, skipping")}return o.debug("Registered system instructions"),a}function ZC(e){let{services:t,jobs:n,insights:o,query:i,getAppInfo:a}=e,s=t.jobQueueService,l=t.logger.child("system"),c=JC({entityService:t.entityService,entityRegistry:t.entityRegistry,jobs:{...n,enqueue:WC(s,"system",!1),enqueueBatch:HC(n,"system"),registerHandler:VC(s,"system")},conversationService:t.conversationService,runtimeUploads:t.runtimeUploadRegistry,attachments:ol(t.attachmentRegistry),logger:l,query:i,getIdentity:()=>t.identityService.getCharacter(),getProfile:()=>t.profileService.getProfile(),getAppInfo:a,searchLimit:10,insights:o,permissionService:t.permissionService},t.mcpService,t.messageBus,l);t.disposables.push(c)}class yp{scope;closePromise=null;closed=!1;constructor(){this.scope=se.runSync(Xe.make())}buildLayer(e){this.assertOpen();let t=se.runSyncExit(Xr.buildWithScope(e,this.scope));if(ot.isFailure(t))throw Pr.squash(t.cause);return t.value}addFinalizer(e){this.assertOpen(),se.runSync(Xe.addFinalizer(this.scope,se.promise(async()=>{await e()})))}addSyncFinalizer(e){this.assertOpen(),se.runSync(Xe.addFinalizer(this.scope,se.sync(()=>{e()})))}async fork(e){if(this.closed)throw Error("Cannot start background work after shell shutdown");await se.runPromise(se.forkIn(e,this.scope))}close(e=ot.void){if(this.closePromise)return this.closePromise;if(this.closed)return Promise.resolve();return this.closed=!0,this.closePromise=se.runPromise(Xe.close(this.scope,e)),this.closePromise}closeSync(e){if(this.closed)return;this.closed=!0,se.runSync(Xe.close(this.scope,e))}assertOpen(){if(this.closed)throw Error("Cannot register cleanup after shell shutdown")}}class oa{config;services;lifecycle;bootloader;initialized=!1;lifecycleState="constructed";bootMode;bootPromise=null;shutdownPromise=null;insightsRegistry;bootTime=Date.now();endpointRegistry=new np;interactionRegistry=new op;httpRouteRegistry=Fs.createFresh();jobs;static createFresh(e,t,n){return new oa(da(e),t,n)}constructor(e,t,n){this.config=e,this.lifecycle=new yp,XC(this,()=>this.httpRouteRegistry.getSnapshot());let o=t?.logger??fr.getInstance(),i=qs.createFresh(o,this.config,n?.processRole);try{this.services=i.initializeServices(this.lifecycle,t),this.jobs=EI(this.services.batchJobManager,this.services.jobQueueService),this.insightsRegistry=II(this.services.entityRegistry),this.bootloader=new tp(this.config,this.services,this.lifecycle,i,n?.processRole,{registerCoreDataSources:()=>jp(this.services,this.config),finalizeHttpRoutes:()=>{this.httpRouteRegistry.finalize(MI(this.services.pluginManager))},registerSystemCapabilities:()=>ZC({services:this.services,jobs:this.jobs,insights:this.insightsRegistry,query:(a,s)=>this.query(a,s),getAppInfo:()=>this.getAppInfo()}),createProjectionInputContext:()=>({entities:this.services.entityService,resolvePrompt:(a,s)=>pa(this.services.entityService,a,s),appInfo:()=>this.getAppInfo(),identityInput:()=>{let a=this.getIdentity(),s=this.getProfile();return QC.parse({brainName:a.name,role:a.role,purpose:a.purpose,values:a.values,profileName:s.name,...s.description!==void 0?{profileDescription:s.description}:{},...s.organization!==void 0?{profileOrganization:s.organization}:{}})}}),createProjectionExecutionContext:()=>({ai:YC(this),logger:this.services.logger.child("ProjectionRuntime")}),...t?.projectionRuntime&&{projectionRuntime:t.projectionRuntime}}),i.wireShell(this.services,this),OI(this.lifecycle,this.services)}catch(a){try{this.lifecycle.closeSync(ot.fail(a))}catch(s){o.error("Failed to roll back Shell service construction",s)}throw a}}getInsightsRegistry(){return this.insightsRegistry}async initialize(e){this.services.logger.debug("Shell.initialize() called");let t=e?.mode;if(this.lifecycleState==="running")return this.services.logger.warn("Shell already initialized"),Promise.resolve();if(this.lifecycleState==="booting"){if(this.bootMode!==t)return Promise.reject(Error(`Shell is already initializing in ${this.bootMode??"normal"} mode; cannot join ${t??"normal"} mode`));return this.bootPromise??Promise.resolve()}if(this.lifecycleState==="closing"||this.lifecycleState==="closed")return Promise.reject(Error("Cannot initialize a closing shell"));if(this.lifecycleState==="failed")return Promise.reject(Error("Cannot initialize a shell after boot failure"));return this.lifecycleState="booting",this.bootMode=t,this.bootPromise=this.boot(e),this.bootPromise}async boot(e){try{if(await this.bootloader.boot(e),this.lifecycleState==="booting"){if(this.lifecycleState="running",this.initialized=!0,e?.mode===void 0)await this.services.messageBus.send({type:Yr.shellReady,payload:{timestamp:new Date().toISOString()},sender:"shell",broadcast:!0}),this.services.logger.debug("Emitted shell ready event")}}catch(t){if(this.initialized=!1,this.services.logger.error("Failed to initialize Shell",t),this.lifecycleState!=="closing")this.lifecycleState="failed";try{await this.lifecycle.close(ot.fail(t))}catch(n){this.services.logger.error("Failed to clean up Shell after initialization failure",n)}throw t}}registerTemplates(e,t){this.services.logger.debug("Registering templates",{pluginId:t,count:Object.keys(e).length});for(let[n,o]of Object.entries(e))this.registerTemplate(n,o,t)}shutdown(){return this.shutdownPromise??=this.shutdownShell(),this.shutdownPromise}async shutdownShell(){if(this.services.logger.debug("Shutting down Shell"),this.lifecycleState==="closed")return;let e=this.bootPromise;if(this.lifecycleState="closing",this.initialized=!1,e)try{await e}catch{}await this.lifecycle.close(),this.lifecycleState="closed",this.services.logger.debug("Shell shutdown complete")}async generateContent(e,t){return this.requireInitialized("Shell content generation"),Op(this.services,e,t)}async query(e,t){this.requireInitialized("Shell query");let n=await this.getAppInfo(),o={...t,appInfo:n,timestamp:new Date().toISOString()},{conversationHistory:i,...a}=o;return KC.parse(await this.generateContent({prompt:e,templateName:Zo.KNOWLEDGE_QUERY,...i&&{conversationHistory:i},data:a,interfacePermissionGrant:"public"}))}registerPlugin(e){this.requireInitialized("Plugin registration"),this.services.pluginManager.registerPlugin(e)}isInitialized(){return this.initialized}requireInitialized(e){if(!this.initialized)throw Error(`${e} attempted before initialization`)}getEntityService(){return this.services.entityService}getConversationService(){return this.services.conversationService}getEntityRegistry(){return this.services.entityRegistry}async generateObject(e,t,n){this.requireInitialized("Shell generateObject");let{object:o}=await this.services.aiService.generateObject("You are a helpful assistant. Respond with the requested structured data.",e,t,n);return{object:o}}async judge(e){return this.requireInitialized("Shell judge"),this.services.aiService.judge(e)}getAIService(){return this.services.aiService}generateImage(e,t){return this.services.aiService.generateImage(e,t)}canGenerateImages(){return this.services.aiService.canGenerateImages()}getPluginManager(){return this.services.pluginManager}getContentService(){return this.services.contentService}getRenderService(){return this.services.renderService}getAttachmentRegistry(){return ol(this.services.attachmentRegistry)}getRuntimeUploadRegistry(){return e0(this.services.runtimeUploadRegistry)}getRuntimeState(){return this.services.runtimeStateService}getRecurringChecks(e){return this.services.recurringCheckService.namespace(e)}isJobQueueWorkerRunning(){return this.services.jobQueueWorker.isWorkerRunning()}getMessageBus(){return this.services.messageBus}getLogger(){return this.services.logger}getJobQueueService(){return this.services.jobQueueService}getMCPService(){return this.services.mcpService}listToolsForPermissionLevel(e){return this.services.mcpService.listToolsForPermissionLevel(e).map(({pluginId:t,tool:n})=>({name:n.name,description:n.description,pluginId:t}))}getPermissionService(){return this.services.permissionService}getAgentService(){return this.services.agentService}registerTools(e,t){for(let n of t)this.services.mcpService.registerTool(e,n)}registerResources(e,t){for(let n of t)this.services.mcpService.registerResource(e,n)}registerResourceTemplate(e,t){this.services.mcpService.registerResourceTemplate(e,t)}registerPrompt(e,t){this.services.mcpService.registerPrompt(e,t)}registerInstructions(e,t){if(this.services.mcpService.registerInstructions(e,t),this.initialized)this.services.agentService.invalidateAgent()}async unregisterPluginCapabilities(e){this.services.mcpService.unregisterPlugin?.(e),this.services.jobQueueService.unregisterPluginHandlers(e),this.endpointRegistry.unregister(e),this.interactionRegistry.unregister(e);for(let n of this.services.templateRegistry.getNames())if(n.startsWith(`${e}:`))this.services.templateRegistry.unregister(n);let t=this.config.evalHandlerRegistry;if(t){for(let n of t.list())if(n.pluginId===e)t.unregister(e,n.handlerId)}this.services.agentService.invalidateAgent(),await this.services.recurringCheckService.unregisterPlugin(e)}getPluginPackageName(e){return this.services.pluginManager.getPluginPackageName(e)}hasPlugin(e){return this.services.pluginManager.hasPlugin(e)}getPluginHttpRouteManifest(){return this.httpRouteRegistry.getManifest()}getPluginApiRoutes(){return this.httpRouteRegistry.getApiRoutes()}getPluginWebRoutes(){return this.httpRouteRegistry.getWebRoutes()}registerDaemon(e,t,n){this.services.daemonRegistry.register(e,t,n)}registerEndpoint(e){this.endpointRegistry.register(e)}listEndpoints(){return this.endpointRegistry.list()}registerInteraction(e){this.interactionRegistry.register(e)}listInteractions(){return this.interactionRegistry.list()}registerTemplate(e,t,n){let o=n?`${n}:${e}`:`shell:${e}`;this.services.templateRegistry.register(o,t),this.services.logger.debug(`Registered template: ${o}`)}getTemplate(e){return this.services.templateRegistry.get(e)}getDataSourceRegistry(){return this.services.dataSourceRegistry}getIdentity(){return this.services.identityService.getCharacter()}getProfile(){return this.services.profileService.getProfile()}getProfileKindRegistry(){return this.services.profileKindRegistry}getChannelRegistry(){return this.services.channelRegistry}getInboxRegistry(){return this.services.inboxRegistry}getInboxFollowUpRegistry(){return this.services.inboxFollowUpRegistry}getOperationalHealthRegistry(){return this.services.operationalHealthRegistry}getAccountSettingsRegistry(){return this.services.accountSettingsRegistry}getDomain(){return this.config.siteBaseUrl}getLocalSiteUrl(){return this.config.localSiteUrl}shouldPreferLocalUrls(){return this.config.preferLocalUrls}getThemeCSS(){return this.config.themeCSS}getSpaces(){return this.config.spaces}getDataDir(){return this.config.dataDir}getGitBrokerSocket(){return this.config.gitBrokerSocket}getGitBrokerCheckout(){return this.config.gitBrokerCheckout}registerEvalHandler(e,t,n){this.config.evalHandlerRegistry?.register(e,t,n)}async getAppInfo(){return kp({config:this.config,services:this.services,bootTime:this.bootTime,endpoints:()=>this.listEndpoints(),interactions:()=>this.listInteractions()})}getRuntimeReadiness(){return Ap(this.services)}}var t0={kind:"service",serviceId:"brain-cli"},vp=`${t0.kind}:${t0.serviceId}`;var YJ=r.object({provider:r.enum(["hetzner","docker"]).default("hetzner"),serverSize:r.string().default("cx33"),location:r.string().default("fsn1"),domain:r.string().optional(),docker:r.object({enabled:r.boolean().default(!0),image:r.string().optional()}).prefault({}),ports:r.object({default:r.number().default(3333),preview:r.number().default(4321),production:r.number().default(8080)}).prefault({}),cdn:r.object({enabled:r.boolean().default(!1),provider:r.enum(["bunny","none"]).default("none")}).prefault({}),dns:r.object({enabled:r.boolean().default(!1),provider:r.enum(["bunny","none"]).default("none")}).prefault({}),paths:r.object({install:r.string().optional(),data:r.string().optional()}).prefault({})}),n0=r.object({name:r.string().default("brain-app"),version:r.string().default("1.0.0"),database:r.string().optional(),aiApiKey:r.string().optional(),aiImageKey:r.string().optional(),aiModel:r.string().optional(),aiReasoningEffort:eo.optional(),logLevel:Xn.optional(),logFile:r.string().optional(),profileKind:r.string().trim().min(1).optional(),plugins:r.array(ua).default([]),spaces:r.array(r.string()).default([]),identity:r0.optional(),agentInstructions:r.array(r.string()).optional(),deployment:YJ.prefault({})});async function g0(e,t){await Sn({label:"entity",config:e,schema:{assets:i0,entities:o0,entityMutationReceipts:a0,projectionDirtyInputs:s0,projectionWaves:l0,projectionIncidents:c0,projectionWaveInputs:u0,projectionWaveRules:d0,projectionRuleMemos:p0},migrationsFolder:wn(import.meta.url,"entity-service"),authTokenEnv:"DATABASE_AUTH_TOKEN",logger:t,afterMigrate:m0})}async function y0(e,t){await Sn({label:"job-queue",config:e,schema:{jobQueue:f0,jobWorkerSessions:h0},migrationsFolder:wn(import.meta.url,"job-queue"),authTokenEnv:"JOB_QUEUE_DATABASE_AUTH_TOKEN",logger:t})}async function S0(e,t){await Sn({label:"conversation",config:e,schema:{conversations:v0,messages:b0,summaryTracking:_0},migrationsFolder:wn(import.meta.url,"conversation-service"),authTokenEnv:"CONVERSATION_DATABASE_AUTH_TOKEN",logger:t})}async function w0(e,t){await Sn({label:"runtime-state",config:e,schema:{runtimeStateRecords:$e},migrationsFolder:wn(import.meta.url,"runtime-state"),authTokenEnv:"RUNTIME_STATE_DATABASE_AUTH_TOKEN",logger:t})}import{mkdir as bp}from"fs/promises";import{isAbsolute as XJ}from"path";function x0(e=process.env){return{dataDir:e.XDG_DATA_HOME??"./data",cacheDir:e.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function T0(e=process.env){let t=e.BRAIN_GIT_BROKER_CHECKOUT;if(!t)return;if(!XJ(t))throw Error(`Git broker checkout path must be absolute: ${t}`);return t}function I0(e=process.env){let t=e.BRAIN_GIT_BROKER_SOCKET;if(!t)return;let n=107;if(Buffer.byteLength(t)>n)throw Error(`Git broker socket path is too long for a unix socket (${Buffer.byteLength(t)} > ${n} bytes): ${t}`);return t}function C0(e=process.env){return In(x0(e))}async function k0(e=process.env){let t=x0(e);try{await bp(t.dataDir,{recursive:!0}),await bp(t.cacheDir,{recursive:!0}),await bp(t.distDir,{recursive:!0})}catch(n){let o=n instanceof Error&&n.message.includes("EACCES")?`Cannot create data directories \u2014 permission denied. Run from a writable directory or check permissions on ${t.dataDir}`:`Cannot create data directories: ${Ce(n)}`;throw Error(o,{cause:n})}return In(t)}class _p{logger;migrations;constructor(e,t){this.logger=e,this.migrations=t??{getStandardConfigWithDirectories:()=>k0(),migrateEntities:g0,migrateJobQueue:y0,migrateConversations:S0,migrateRuntimeState:w0}}async runAllMigrations(e){this.logger.debug("Running database migrations...");let t=await this.migrations.getStandardConfigWithDirectories();if(e?.database)t.database.url=e.database;if(e?.jobQueueDatabase)t.jobQueueDatabase.url=e.jobQueueDatabase;if(e?.conversationDatabase)t.conversationDatabase.url=e.conversationDatabase;if(e?.runtimeStateDatabase)t.runtimeStateDatabase.url=e.runtimeStateDatabase;await this.migrateEntityDatabase(t),await this.migrateJobQueueDatabase(t),await this.migrateConversationDatabase(t),await this.migrateRuntimeStateDatabase(t),this.logger.debug("All database migrations completed successfully")}async migrateEntityDatabase(e){this.logger.debug("Running entity database migrations..."),await this.migrations.migrateEntities({url:e.database.url,...e.database.authToken&&{authToken:e.database.authToken}},this.logger)}async migrateJobQueueDatabase(e){this.logger.debug("Running job queue database migrations..."),await this.migrations.migrateJobQueue({url:e.jobQueueDatabase.url,...e.jobQueueDatabase.authToken&&{authToken:e.jobQueueDatabase.authToken}},this.logger)}async migrateConversationDatabase(e){this.logger.debug("Running conversation database migrations..."),await this.migrations.migrateConversations({url:e.conversationDatabase.url,...e.conversationDatabase.authToken&&{authToken:e.conversationDatabase.authToken}},this.logger)}async migrateRuntimeStateDatabase(e){this.logger.debug("Running runtime state database migrations..."),await this.migrations.migrateRuntimeState({url:e.runtimeStateDatabase.url,...e.runtimeStateDatabase.authToken&&{authToken:e.runtimeStateDatabase.authToken}},this.logger)}}var e4="NODE_ENV";function t4(){return process.env[e4]}function R0(){return t4()!=="production"}var r4="startup-check";function n4(e){let n={...n0.parse(e??{}),plugins:e?.plugins??[]};if(e?.permissions)n.permissions=e.permissions;if(e?.spaces)n.spaces=e.spaces;if(e?.cliConfig)n.cliConfig=e.cliConfig;if(e?.shellConfig)n.shellConfig=e.shellConfig;return n}function o4(e,t){let n={plugins:e.plugins??[],...e.shellConfig};return i4(n),a4(e,n),s4(e,n,t),l4(e,n),c4(e,n),u4(e,n),d4(e,n),p4(e,n),m4(e,n),n}function i4(e){let t=C0();e.database??=t.database,e.jobQueueDatabase??=t.jobQueueDatabase,e.conversationDatabase??=t.conversationDatabase,e.runtimeStateDatabase??=t.runtimeStateDatabase,e.embeddingDatabase??=t.embeddingDatabase,e.embedding??=t.embedding,e.gitBrokerSocket??=I0(),e.gitBrokerCheckout??=T0()}function a4(e,t){if(e.database)t.database={url:e.database};if(e.profileKind)t.profileKind=e.profileKind;t.features={}}function s4(e,t,n){let o=n?.mode==="startup-check";if(!e.aiApiKey&&!e.aiImageKey&&!e.aiModel&&!e.aiReasoningEffort&&!o)return;t.ai={...t.ai,...o&&!t.ai?.apiKey&&{apiKey:r4},...e.aiApiKey&&{apiKey:e.aiApiKey},...e.aiImageKey&&{imageApiKey:e.aiImageKey},...e.aiModel&&{model:e.aiModel},...e.aiReasoningEffort&&{reasoningEffort:e.aiReasoningEffort}}}function l4(e,t){if(!e.logLevel&&!e.logFile)return;t.logging={level:e.logLevel??"info",format:"text",context:e.name,...e.logFile&&{file:e.logFile}}}function c4(e,t){let n=e.permissions?.rules??[];t.permissions={...e.permissions,rules:n.some((o)=>o.pattern===vp)?n:[{pattern:vp,level:"admin"},...n]}}function u4(e,t){if(e.spaces)t.spaces=e.spaces}function d4(e,t){if(e.identity)t.identity=e.identity}function p4(e,t){if(e.agentInstructions)t.agentInstructions=e.agentInstructions}function m4(e,t){if(t.name=e.name,t.version=e.version,e.deployment.domain)t.siteBaseUrl=e.deployment.domain;t.localSiteUrl=`http://localhost:${e.deployment.ports.production}`,t.preferLocalUrls=R0()}class wp{shell=null;config;signalScope=null;signalShutdownFiber=null;stopPromise=null;hasCLI=!1;static create(e,t){return new wp(n4(e),t)}constructor(e,t){if(this.config=e,this.hasCLI=process.argv.slice(2).includes("--cli"),t)this.shell=t}async migrate(){let e=fr.getInstance();await new _p(e).runAllMigrations({database:this.config.shellConfig?.database?.url??this.config.database,jobQueueDatabase:this.config.shellConfig?.jobQueueDatabase?.url,conversationDatabase:this.config.shellConfig?.conversationDatabase?.url,runtimeStateDatabase:this.config.shellConfig?.runtimeStateDatabase?.url})}createShell(e,t){this.shell=oa.createFresh(o4(this.config,e),void 0,{...t&&{processRole:t}})}async registerCLIInterface(){if(!this.hasCLI)return;let e=this.getShell().getPluginManager(),{CLIInterface:t}=await import("./index-xkfmxqz3.js"),n=new t(this.config.cliConfig);e.registerPlugin(n)}async initialize(e,t){if(!this.shell){if(!t?.migrationsCompleted)await this.migrate();this.createShell(e,t?.processRole)}await this.registerCLIInterface(),await this.getShell().initialize(e)}async start(){if(this.stopPromise)return;this.setupSignalHandlers()}stop(){return this.stopPromise??=this.stopApp(),this.stopPromise}async stopApp(){await this.closeSignalScope(),await this.shell?.shutdown()}async run(e){let n={debug:Ut.DEBUG,info:Ut.INFO,warn:Ut.WARN,error:Ut.ERROR}[this.config.logLevel??"info"]??Ut.INFO,o=fr.createFresh({level:n,context:this.config.name,useStderr:this.hasCLI});if(this.hasCLI)fr.getInstance().setUseStderr(!0);try{await this.initialize(void 0,e),await this.start(),e?.onRuntimeReady?.(),o.info(`\u2705 ${this.config.name} v${this.config.version} ready`),process.stdin.resume()}catch(i){o.error(`\u274C Failed to start ${this.config.name}:`,i),process.exit(1)}}static async run(e,t,n){await wp.create(e,t).run(n)}setupSignalHandlers(){if(this.signalScope)return;let e=se.runSync(Xe.make()),t=()=>{this.requestGracefulShutdown("SIGINT")},n=()=>{this.requestGracefulShutdown("SIGTERM")},o=Sp(["SIGINT"],t),i=Sp(["SIGTERM"],n);se.runSync(Xe.addFinalizer(e,se.sync(()=>{i(),o()}))),this.signalScope=e}requestGracefulShutdown(e){if(this.signalShutdownFiber)return;let t=fr.getInstance();t.info(`
|
|
190
|
+
`)}var Uo="system",QJ=r.object({toolName:r.string(),args:r.unknown(),...GC.partial().shape});function nl(e,t,n,o,i){for(let a of e)try{t(a)}catch{i.debug(`System ${o} ${n(a)} already registered, skipping`)}}function JC(e,t,n,o){let i=UC(e);nl(i,(d)=>t.registerTool(Uo,d),(d)=>d.name,"tool",o);let a=n.subscribe(BC.toolExecute(Uo),async(d)=>{let m=QJ.safeParse(d.payload);if(!m.success)return{success:!1,error:"Invalid system tool execute payload"};let{toolName:p,args:f,interfaceType:g,actor:h,conversationId:v,channelId:x,userPermissionLevel:_}=m.data,y=i.find((C)=>C.name===p);if(!y)return{success:!1,error:`System tool not found: ${p}`};let w={interfaceType:g??"system",actor:h??{kind:"service",serviceId:"system"}};if(v)w.conversationId=v;if(x)w.channelId=x;if(_)w.userPermissionLevel=_;return{success:!0,data:await y.handler(f,w)}});o.debug(`Registered ${i.length} system tools`);let s=qC(e);nl(s,(d)=>t.registerResource(Uo,d),(d)=>d.uri,"resource",o),o.debug(`Registered ${s.length} system resources`);let l=LC(e);nl(l,(d)=>t.registerResourceTemplate(Uo,d),(d)=>d.uriTemplate,"resource template",o),o.debug(`Registered ${l.length} system resource templates`);let c=$C(e);nl(c,(d)=>t.registerPrompt(Uo,d),(d)=>d.name,"prompt",o),o.debug(`Registered ${c.length} system prompts`);let u=FC(e);try{t.registerInstructions(Uo,u)}catch{o.debug("System instructions already registered, skipping")}return o.debug("Registered system instructions"),a}function ZC(e){let{services:t,jobs:n,insights:o,query:i,getAppInfo:a}=e,s=t.jobQueueService,l=t.logger.child("system"),c=JC({entityService:t.entityService,entityRegistry:t.entityRegistry,jobs:{...n,enqueue:WC(s,"system",!1),enqueueBatch:HC(n,"system"),registerHandler:VC(s,"system")},conversationService:t.conversationService,runtimeUploads:t.runtimeUploadRegistry,attachments:ol(t.attachmentRegistry),logger:l,query:i,getIdentity:()=>t.identityService.getCharacter(),getProfile:()=>t.profileService.getProfile(),getAppInfo:a,searchLimit:10,insights:o,permissionService:t.permissionService},t.mcpService,t.messageBus,l);t.disposables.push(c)}class yp{scope;closePromise=null;closed=!1;constructor(){this.scope=se.runSync(Xe.make())}buildLayer(e){this.assertOpen();let t=se.runSyncExit(Xr.buildWithScope(e,this.scope));if(ot.isFailure(t))throw Pr.squash(t.cause);return t.value}addFinalizer(e){this.assertOpen(),se.runSync(Xe.addFinalizer(this.scope,se.promise(async()=>{await e()})))}addSyncFinalizer(e){this.assertOpen(),se.runSync(Xe.addFinalizer(this.scope,se.sync(()=>{e()})))}async fork(e){if(this.closed)throw Error("Cannot start background work after shell shutdown");await se.runPromise(se.forkIn(e,this.scope))}close(e=ot.void){if(this.closePromise)return this.closePromise;if(this.closed)return Promise.resolve();return this.closed=!0,this.closePromise=se.runPromise(Xe.close(this.scope,e)),this.closePromise}closeSync(e){if(this.closed)return;this.closed=!0,se.runSync(Xe.close(this.scope,e))}assertOpen(){if(this.closed)throw Error("Cannot register cleanup after shell shutdown")}}class oa{config;services;lifecycle;bootloader;initialized=!1;lifecycleState="constructed";bootMode;bootPromise=null;shutdownPromise=null;insightsRegistry;bootTime=Date.now();endpointRegistry=new np;interactionRegistry=new op;httpRouteRegistry=Fs.createFresh();jobs;static createFresh(e,t,n){return new oa(da(e),t,n)}constructor(e,t,n){this.config=e,this.lifecycle=new yp,XC(this,()=>this.httpRouteRegistry.getSnapshot());let o=t?.logger??fr.getInstance(),i=qs.createFresh(o,this.config,n?.processRole);try{this.services=i.initializeServices(this.lifecycle,t),this.jobs=EI(this.services.batchJobManager,this.services.jobQueueService),this.insightsRegistry=II(this.services.entityRegistry),this.bootloader=new tp(this.config,this.services,this.lifecycle,i,n?.processRole,{registerCoreDataSources:()=>jp(this.services,this.config),finalizeHttpRoutes:()=>{this.httpRouteRegistry.finalize(MI(this.services.pluginManager))},registerSystemCapabilities:()=>ZC({services:this.services,jobs:this.jobs,insights:this.insightsRegistry,query:(a,s)=>this.query(a,s),getAppInfo:()=>this.getAppInfo()}),createProjectionInputContext:()=>({entities:this.services.entityService,resolvePrompt:(a,s)=>pa(this.services.entityService,a,s),appInfo:()=>this.getAppInfo(),identityInput:()=>{let a=this.getIdentity(),s=this.getProfile();return QC.parse({brainName:a.name,role:a.role,purpose:a.purpose,values:a.values,profileName:s.name,...s.description!==void 0?{profileDescription:s.description}:{},...s.organization!==void 0?{profileOrganization:s.organization}:{}})}}),createProjectionExecutionContext:()=>({ai:YC(this),logger:this.services.logger.child("ProjectionRuntime")}),...t?.projectionRuntime&&{projectionRuntime:t.projectionRuntime}}),i.wireShell(this.services,this),OI(this.lifecycle,this.services)}catch(a){try{this.lifecycle.closeSync(ot.fail(a))}catch(s){o.error("Failed to roll back Shell service construction",s)}throw a}}getInsightsRegistry(){return this.insightsRegistry}async initialize(e){this.services.logger.debug("Shell.initialize() called");let t=e?.mode;if(this.lifecycleState==="running")return this.services.logger.warn("Shell already initialized"),Promise.resolve();if(this.lifecycleState==="booting"){if(this.bootMode!==t)return Promise.reject(Error(`Shell is already initializing in ${this.bootMode??"normal"} mode; cannot join ${t??"normal"} mode`));return this.bootPromise??Promise.resolve()}if(this.lifecycleState==="closing"||this.lifecycleState==="closed")return Promise.reject(Error("Cannot initialize a closing shell"));if(this.lifecycleState==="failed")return Promise.reject(Error("Cannot initialize a shell after boot failure"));return this.lifecycleState="booting",this.bootMode=t,this.bootPromise=this.boot(e),this.bootPromise}async boot(e){try{if(await this.bootloader.boot(e),this.lifecycleState==="booting"){if(this.lifecycleState="running",this.initialized=!0,e?.mode===void 0)await this.services.messageBus.send({type:Yr.shellReady,payload:{timestamp:new Date().toISOString()},sender:"shell",broadcast:!0}),this.services.logger.debug("Emitted shell ready event")}}catch(t){if(this.initialized=!1,this.services.logger.error("Failed to initialize Shell",t),this.lifecycleState!=="closing")this.lifecycleState="failed";try{await this.lifecycle.close(ot.fail(t))}catch(n){this.services.logger.error("Failed to clean up Shell after initialization failure",n)}throw t}}registerTemplates(e,t){this.services.logger.debug("Registering templates",{pluginId:t,count:Object.keys(e).length});for(let[n,o]of Object.entries(e))this.registerTemplate(n,o,t)}shutdown(){return this.shutdownPromise??=this.shutdownShell(),this.shutdownPromise}async shutdownShell(){if(this.services.logger.debug("Shutting down Shell"),this.lifecycleState==="closed")return;let e=this.bootPromise;if(this.lifecycleState="closing",this.initialized=!1,e)try{await e}catch{}await this.lifecycle.close(),this.lifecycleState="closed",this.services.logger.debug("Shell shutdown complete")}async generateContent(e,t){return this.requireInitialized("Shell content generation"),Op(this.services,e,t)}async query(e,t){this.requireInitialized("Shell query");let n=await this.getAppInfo(),o={...t,appInfo:n,timestamp:new Date().toISOString()},{conversationHistory:i,...a}=o;return KC.parse(await this.generateContent({prompt:e,templateName:Zo.KNOWLEDGE_QUERY,...i&&{conversationHistory:i},data:a,interfacePermissionGrant:"public"}))}registerPlugin(e){this.requireInitialized("Plugin registration"),this.services.pluginManager.registerPlugin(e)}isInitialized(){return this.initialized}requireInitialized(e){if(!this.initialized)throw Error(`${e} attempted before initialization`)}getEntityService(){return this.services.entityService}getConversationService(){return this.services.conversationService}getEntityRegistry(){return this.services.entityRegistry}async generateObject(e,t,n){this.requireInitialized("Shell generateObject");let{object:o}=await this.services.aiService.generateObject("You are a helpful assistant. Respond with the requested structured data.",e,t,n);return{object:o}}async judge(e){return this.requireInitialized("Shell judge"),this.services.aiService.judge(e)}getAIService(){return this.services.aiService}generateImage(e,t){return this.services.aiService.generateImage(e,t)}canGenerateImages(){return this.services.aiService.canGenerateImages()}getPluginManager(){return this.services.pluginManager}getContentService(){return this.services.contentService}getRenderService(){return this.services.renderService}getAttachmentRegistry(){return ol(this.services.attachmentRegistry)}getRuntimeUploadRegistry(){return e0(this.services.runtimeUploadRegistry)}getRuntimeState(){return this.services.runtimeStateService}getRecurringChecks(e){return this.services.recurringCheckService.namespace(e)}isJobQueueWorkerRunning(){return this.services.jobQueueWorker.isWorkerRunning()}getMessageBus(){return this.services.messageBus}getLogger(){return this.services.logger}getJobQueueService(){return this.services.jobQueueService}getMCPService(){return this.services.mcpService}listToolsForPermissionLevel(e){return this.services.mcpService.listToolsForPermissionLevel(e).map(({pluginId:t,tool:n})=>({name:n.name,description:n.description,pluginId:t}))}getPermissionService(){return this.services.permissionService}getAgentService(){return this.services.agentService}registerTools(e,t){for(let n of t)this.services.mcpService.registerTool(e,n)}registerResources(e,t){for(let n of t)this.services.mcpService.registerResource(e,n)}registerResourceTemplate(e,t){this.services.mcpService.registerResourceTemplate(e,t)}registerPrompt(e,t){this.services.mcpService.registerPrompt(e,t)}registerInstructions(e,t){if(this.services.mcpService.registerInstructions(e,t),this.initialized)this.services.agentService.invalidateAgent()}async unregisterPluginCapabilities(e){this.services.mcpService.unregisterPlugin?.(e),this.services.jobQueueService.unregisterPluginHandlers(e),this.endpointRegistry.unregister(e),this.interactionRegistry.unregister(e);for(let n of this.services.templateRegistry.getNames())if(n.startsWith(`${e}:`))this.services.templateRegistry.unregister(n);let t=this.config.evalHandlerRegistry;if(t){for(let n of t.list())if(n.pluginId===e)t.unregister(e,n.handlerId)}this.services.agentService.invalidateAgent(),await this.services.recurringCheckService.unregisterPlugin(e)}getPluginPackageName(e){return this.services.pluginManager.getPluginPackageName(e)}hasPlugin(e){return this.services.pluginManager.hasPlugin(e)}getPluginHttpRouteManifest(){return this.httpRouteRegistry.getManifest()}getPluginApiRoutes(){return this.httpRouteRegistry.getApiRoutes()}getPluginWebRoutes(){return this.httpRouteRegistry.getWebRoutes()}registerDaemon(e,t,n){this.services.daemonRegistry.register(e,t,n)}registerEndpoint(e){this.endpointRegistry.register(e)}listEndpoints(){return this.endpointRegistry.list()}registerInteraction(e){this.interactionRegistry.register(e)}listInteractions(){return this.interactionRegistry.list()}registerTemplate(e,t,n){let o=n?`${n}:${e}`:`shell:${e}`;this.services.templateRegistry.register(o,t),this.services.logger.debug(`Registered template: ${o}`)}getTemplate(e){return this.services.templateRegistry.get(e)}getDataSourceRegistry(){return this.services.dataSourceRegistry}getIdentity(){return this.services.identityService.getCharacter()}getProfile(){return this.services.profileService.getProfile()}getProfileKindRegistry(){return this.services.profileKindRegistry}getChannelRegistry(){return this.services.channelRegistry}getInboxRegistry(){return this.services.inboxRegistry}getInboxFollowUpRegistry(){return this.services.inboxFollowUpRegistry}getOperationalHealthRegistry(){return this.services.operationalHealthRegistry}getAccountSettingsRegistry(){return this.services.accountSettingsRegistry}getDomain(){return this.config.siteBaseUrl}getLocalSiteUrl(){return this.config.localSiteUrl}shouldPreferLocalUrls(){return this.config.preferLocalUrls}getThemeCSS(){return this.config.themeCSS}getSpaces(){return this.config.spaces}getDataDir(){return this.config.dataDir}getGitBrokerSocket(){return this.config.gitBrokerSocket}getGitBrokerCheckout(){return this.config.gitBrokerCheckout}registerEvalHandler(e,t,n){this.config.evalHandlerRegistry?.register(e,t,n)}async getAppInfo(){return kp({config:this.config,services:this.services,bootTime:this.bootTime,endpoints:()=>this.listEndpoints(),interactions:()=>this.listInteractions()})}getRuntimeReadiness(){return Ap(this.services)}}var t0={kind:"service",serviceId:"brain-cli"},vp=`${t0.kind}:${t0.serviceId}`;var YJ=r.object({provider:r.enum(["hetzner","docker"]).default("hetzner"),serverSize:r.string().default("cx33"),location:r.string().default("fsn1"),domain:r.string().optional(),docker:r.object({enabled:r.boolean().default(!0),image:r.string().optional()}).prefault({}),ports:r.object({default:r.number().default(3333),preview:r.number().default(4321),production:r.number().default(8080)}).prefault({}),cdn:r.object({enabled:r.boolean().default(!1),provider:r.enum(["bunny","none"]).default("none")}).prefault({}),dns:r.object({enabled:r.boolean().default(!1),provider:r.enum(["bunny","none"]).default("none")}).prefault({}),paths:r.object({install:r.string().optional(),data:r.string().optional()}).prefault({})}),n0=r.object({name:r.string().default("brain-app"),version:r.string().default("1.0.0"),database:r.string().optional(),aiApiKey:r.string().optional(),aiImageKey:r.string().optional(),aiModel:r.string().optional(),aiReasoningEffort:eo.optional(),logLevel:Xn.optional(),logFile:r.string().optional(),profileKind:r.string().trim().min(1).optional(),plugins:r.array(ua).default([]),spaces:r.array(r.string()).default([]),identity:r0.optional(),agentInstructions:r.array(r.string()).optional(),deployment:YJ.prefault({})});async function g0(e,t){await Sn({label:"entity",config:e,schema:{assets:i0,entities:o0,entityMutationReceipts:a0,projectionDirtyInputs:s0,projectionWaves:l0,projectionIncidents:c0,projectionWaveInputs:u0,projectionWaveRules:d0,projectionRuleMemos:p0},migrationsFolder:wn(import.meta.url,"entity-service"),authTokenEnv:"DATABASE_AUTH_TOKEN",logger:t,afterMigrate:m0})}async function y0(e,t){await Sn({label:"job-queue",config:e,schema:{jobQueue:f0,jobWorkerSessions:h0},migrationsFolder:wn(import.meta.url,"job-queue"),authTokenEnv:"JOB_QUEUE_DATABASE_AUTH_TOKEN",logger:t})}async function S0(e,t){await Sn({label:"conversation",config:e,schema:{conversations:v0,messages:b0,summaryTracking:_0},migrationsFolder:wn(import.meta.url,"conversation-service"),authTokenEnv:"CONVERSATION_DATABASE_AUTH_TOKEN",logger:t})}async function w0(e,t){await Sn({label:"runtime-state",config:e,schema:{runtimeStateRecords:$e},migrationsFolder:wn(import.meta.url,"runtime-state"),authTokenEnv:"RUNTIME_STATE_DATABASE_AUTH_TOKEN",logger:t})}import{mkdir as bp}from"fs/promises";import{isAbsolute as XJ}from"path";function x0(e=process.env){return{dataDir:e.XDG_DATA_HOME??"./data",cacheDir:e.XDG_CACHE_HOME??"./cache",distDir:"./dist"}}function T0(e=process.env){let t=e.BRAIN_GIT_BROKER_CHECKOUT;if(!t)return;if(!XJ(t))throw Error(`Git broker checkout path must be absolute: ${t}`);return t}function I0(e=process.env){let t=e.BRAIN_GIT_BROKER_SOCKET;if(!t)return;let n=107;if(Buffer.byteLength(t)>n)throw Error(`Git broker socket path is too long for a unix socket (${Buffer.byteLength(t)} > ${n} bytes): ${t}`);return t}function C0(e=process.env){return In(x0(e))}async function k0(e=process.env){let t=x0(e);try{await bp(t.dataDir,{recursive:!0}),await bp(t.cacheDir,{recursive:!0}),await bp(t.distDir,{recursive:!0})}catch(n){let o=n instanceof Error&&n.message.includes("EACCES")?`Cannot create data directories \u2014 permission denied. Run from a writable directory or check permissions on ${t.dataDir}`:`Cannot create data directories: ${Ce(n)}`;throw Error(o,{cause:n})}return In(t)}class _p{logger;migrations;constructor(e,t){this.logger=e,this.migrations=t??{getStandardConfigWithDirectories:()=>k0(),migrateEntities:g0,migrateJobQueue:y0,migrateConversations:S0,migrateRuntimeState:w0}}async runAllMigrations(e){this.logger.debug("Running database migrations...");let t=await this.migrations.getStandardConfigWithDirectories();if(e?.database)t.database.url=e.database;if(e?.jobQueueDatabase)t.jobQueueDatabase.url=e.jobQueueDatabase;if(e?.conversationDatabase)t.conversationDatabase.url=e.conversationDatabase;if(e?.runtimeStateDatabase)t.runtimeStateDatabase.url=e.runtimeStateDatabase;await this.migrateEntityDatabase(t),await this.migrateJobQueueDatabase(t),await this.migrateConversationDatabase(t),await this.migrateRuntimeStateDatabase(t),this.logger.debug("All database migrations completed successfully")}async migrateEntityDatabase(e){this.logger.debug("Running entity database migrations..."),await this.migrations.migrateEntities({url:e.database.url,...e.database.authToken&&{authToken:e.database.authToken}},this.logger)}async migrateJobQueueDatabase(e){this.logger.debug("Running job queue database migrations..."),await this.migrations.migrateJobQueue({url:e.jobQueueDatabase.url,...e.jobQueueDatabase.authToken&&{authToken:e.jobQueueDatabase.authToken}},this.logger)}async migrateConversationDatabase(e){this.logger.debug("Running conversation database migrations..."),await this.migrations.migrateConversations({url:e.conversationDatabase.url,...e.conversationDatabase.authToken&&{authToken:e.conversationDatabase.authToken}},this.logger)}async migrateRuntimeStateDatabase(e){this.logger.debug("Running runtime state database migrations..."),await this.migrations.migrateRuntimeState({url:e.runtimeStateDatabase.url,...e.runtimeStateDatabase.authToken&&{authToken:e.runtimeStateDatabase.authToken}},this.logger)}}var e4="NODE_ENV";function t4(){return process.env[e4]}function R0(){return t4()!=="production"}var r4="startup-check";function n4(e){let n={...n0.parse(e??{}),plugins:e?.plugins??[]};if(e?.permissions)n.permissions=e.permissions;if(e?.spaces)n.spaces=e.spaces;if(e?.cliConfig)n.cliConfig=e.cliConfig;if(e?.shellConfig)n.shellConfig=e.shellConfig;return n}function o4(e,t){let n={plugins:e.plugins??[],...e.shellConfig};return i4(n),a4(e,n),s4(e,n,t),l4(e,n),c4(e,n),u4(e,n),d4(e,n),p4(e,n),m4(e,n),n}function i4(e){let t=C0();e.database??=t.database,e.jobQueueDatabase??=t.jobQueueDatabase,e.conversationDatabase??=t.conversationDatabase,e.runtimeStateDatabase??=t.runtimeStateDatabase,e.embeddingDatabase??=t.embeddingDatabase,e.embedding??=t.embedding,e.gitBrokerSocket??=I0(),e.gitBrokerCheckout??=T0()}function a4(e,t){if(e.database)t.database={url:e.database};if(e.profileKind)t.profileKind=e.profileKind;t.features={}}function s4(e,t,n){let o=n?.mode==="startup-check";if(!e.aiApiKey&&!e.aiImageKey&&!e.aiModel&&!e.aiReasoningEffort&&!o)return;t.ai={...t.ai,...o&&!t.ai?.apiKey&&{apiKey:r4},...e.aiApiKey&&{apiKey:e.aiApiKey},...e.aiImageKey&&{imageApiKey:e.aiImageKey},...e.aiModel&&{model:e.aiModel},...e.aiReasoningEffort&&{reasoningEffort:e.aiReasoningEffort}}}function l4(e,t){if(!e.logLevel&&!e.logFile)return;t.logging={level:e.logLevel??"info",format:"text",context:e.name,...e.logFile&&{file:e.logFile}}}function c4(e,t){let n=e.permissions?.rules??[];t.permissions={...e.permissions,rules:n.some((o)=>o.pattern===vp)?n:[{pattern:vp,level:"admin"},...n]}}function u4(e,t){if(e.spaces)t.spaces=e.spaces}function d4(e,t){if(e.identity)t.identity=e.identity}function p4(e,t){if(e.agentInstructions)t.agentInstructions=e.agentInstructions}function m4(e,t){if(t.name=e.name,t.version=e.version,e.deployment.domain)t.siteBaseUrl=e.deployment.domain;t.localSiteUrl=`http://localhost:${e.deployment.ports.production}`,t.preferLocalUrls=R0()}class wp{shell=null;config;signalScope=null;signalShutdownFiber=null;stopPromise=null;hasCLI=!1;static create(e,t){return new wp(n4(e),t)}constructor(e,t){if(this.config=e,this.hasCLI=process.argv.slice(2).includes("--cli"),t)this.shell=t}async migrate(){let e=fr.getInstance();await new _p(e).runAllMigrations({database:this.config.shellConfig?.database?.url??this.config.database,jobQueueDatabase:this.config.shellConfig?.jobQueueDatabase?.url,conversationDatabase:this.config.shellConfig?.conversationDatabase?.url,runtimeStateDatabase:this.config.shellConfig?.runtimeStateDatabase?.url})}createShell(e,t){this.shell=oa.createFresh(o4(this.config,e),void 0,{...t&&{processRole:t}})}async registerCLIInterface(){if(!this.hasCLI)return;let e=this.getShell().getPluginManager(),{CLIInterface:t}=await import("./index-d9vfx9ar.js"),n=new t(this.config.cliConfig);e.registerPlugin(n)}async initialize(e,t){if(!this.shell){if(!t?.migrationsCompleted)await this.migrate();this.createShell(e,t?.processRole)}await this.registerCLIInterface(),await this.getShell().initialize(e)}async start(){if(this.stopPromise)return;this.setupSignalHandlers()}stop(){return this.stopPromise??=this.stopApp(),this.stopPromise}async stopApp(){await this.closeSignalScope(),await this.shell?.shutdown()}async run(e){let n={debug:Ut.DEBUG,info:Ut.INFO,warn:Ut.WARN,error:Ut.ERROR}[this.config.logLevel??"info"]??Ut.INFO,o=fr.createFresh({level:n,context:this.config.name,useStderr:this.hasCLI});if(this.hasCLI)fr.getInstance().setUseStderr(!0);try{await this.initialize(void 0,e),await this.start(),e?.onRuntimeReady?.(),o.info(`\u2705 ${this.config.name} v${this.config.version} ready`),process.stdin.resume()}catch(i){o.error(`\u274C Failed to start ${this.config.name}:`,i),process.exit(1)}}static async run(e,t,n){await wp.create(e,t).run(n)}setupSignalHandlers(){if(this.signalScope)return;let e=se.runSync(Xe.make()),t=()=>{this.requestGracefulShutdown("SIGINT")},n=()=>{this.requestGracefulShutdown("SIGTERM")},o=Sp(["SIGINT"],t),i=Sp(["SIGTERM"],n);se.runSync(Xe.addFinalizer(e,se.sync(()=>{i(),o()}))),this.signalScope=e}requestGracefulShutdown(e){if(this.signalShutdownFiber)return;let t=fr.getInstance();t.info(`
|
|
191
191
|
Received ${e}, shutting down gracefully...`);let n=se.tryPromise({try:()=>this.stop(),catch:(o)=>o}).pipe(se.match({onFailure:(o)=>{t.error("Error during shutdown:",o),process.exit(1)},onSuccess:()=>{process.exit(0)}}));this.signalShutdownFiber=se.runFork(n)}async closeSignalScope(){let e=this.signalScope;if(this.signalScope=null,e)await se.runPromise(Xe.close(e,ot.void))}getShell(){if(!this.shell)throw Error("Shell not initialized. Call initialize() first.");return this.shell}}
|
|
192
192
|
export{Xn as S,eo as T,IO as U,tZ as V,ue as W,mI as X,ra as Y,lC as Z,dC as _,Ys as $,EJ as aa,cp as ba,PJ as ca,Xs as da,MJ as ea,xre as fa,bC as ga,NJ as ha,dp as ia,pp as ja,DJ as ka,zJ as la,UJ as ma,r4 as na,n4 as oa,o4 as pa,wp as qa};
|
|
193
193
|
|
|
194
|
-
//# debugId=
|
|
195
|
-
//# sourceMappingURL=index-
|
|
194
|
+
//# debugId=E76D7102BBB2228D64756E2164756E21
|
|
195
|
+
//# sourceMappingURL=index-s6fa1vbj.js.map
|