@rizom/brain 0.2.0-alpha.247 → 0.2.0-alpha.248
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 +917 -917
- package/dist/chunks/{app-cjwxrsay.js → app-5f8xhs6s.js} +2 -2
- package/dist/chunks/{index-bpvej3jz.js → index-4zsgs8gw.js} +3 -3
- package/dist/chunks/{index-bpvej3jz.js.map → index-4zsgs8gw.js.map} +1 -1
- package/dist/chunks/{index-decwn4ne.js → index-67b6py9k.js} +4 -4
- package/dist/chunks/{index-decwn4ne.js.map → index-67b6py9k.js.map} +2 -2
- package/dist/chunks/{index-2y7fbe2e.js → index-n8fzpy3v.js} +6 -6
- package/dist/chunks/{index-2y7fbe2e.js.map → index-n8fzpy3v.js.map} +1 -1
- package/dist/chunks/{index-7hzbjwbe.js → index-wnkz9tp7.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/model.js +34 -34
- package/dist/model.js.map +1 -1
- package/dist/site.js +2 -2
- package/dist/site.js.map +1 -1
- package/package.json +1 -1
- /package/dist/chunks/{app-cjwxrsay.js.map → app-5f8xhs6s.js.map} +0 -0
- /package/dist/chunks/{index-7hzbjwbe.js.map → index-wnkz9tp7.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{R as a,S as b}from"./index-
|
|
2
|
+
import{R as a,S as b}from"./index-wnkz9tp7.js";import"./index-8p7fsw54.js";import"./index-j4kszm3y.js";import"./index-tqetm7ch.js";import"./index-mtd05v0m.js";import"./index-1c2fwp2j.js";import"./index-jbs1vwsg.js";import"./index-z074cm9f.js";import"./index-xsvc595y.js";import"./index-dqm92xqk.js";import"./index-nxzgd5dw.js";import"./index-a6rck907.js";import"./index-wayf8w0q.js";import"./index-3dbcbegb.js";import"./index-pxn0hgrz.js";export{a as STARTUP_CHECK_API_KEY,b as App};
|
|
3
3
|
|
|
4
4
|
//# debugId=F7414AC863BD46BA64756E2164756E21
|
|
5
|
-
//# sourceMappingURL=app-
|
|
5
|
+
//# sourceMappingURL=app-5f8xhs6s.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{a as C,b as T,c as K}from"./index-9fn97qtp.js";import{e as Y,f as X}from"./index-xnbppay0.js";import"./index-kxyajxq5.js";import{kd as B,nc as P,oc as M,pc as b,qc as O,rc as R,wc as S}from"./index-tqetm7ch.js";import{ge as k}from"./index-mtd05v0m.js";import"./index-1c2fwp2j.js";import"./index-jbs1vwsg.js";import"./index-z074cm9f.js";import"./index-xsvc595y.js";import"./index-dqm92xqk.js";import"./index-nxzgd5dw.js";import"./index-a6rck907.js";import{Xh as z}from"./index-wayf8w0q.js";import{ti as q}from"./index-3dbcbegb.js";import{ui as A,xi as F}from"./index-pxn0hgrz.js";var J=q.object({theme:q.object({primaryColor:q.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:q.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})});var h={name:"@brains/chat-repl",license:"AGPL-3.0-only",version:"0.2.0-alpha.
|
|
2
|
+
import{a as C,b as T,c as K}from"./index-9fn97qtp.js";import{e as Y,f as X}from"./index-xnbppay0.js";import"./index-kxyajxq5.js";import{kd as B,nc as P,oc as M,pc as b,qc as O,rc as R,wc as S}from"./index-tqetm7ch.js";import{ge as k}from"./index-mtd05v0m.js";import"./index-1c2fwp2j.js";import"./index-jbs1vwsg.js";import"./index-z074cm9f.js";import"./index-xsvc595y.js";import"./index-dqm92xqk.js";import"./index-nxzgd5dw.js";import"./index-a6rck907.js";import{Xh as z}from"./index-wayf8w0q.js";import{ti as q}from"./index-3dbcbegb.js";import{ui as A,xi as F}from"./index-pxn0hgrz.js";var J=q.object({theme:q.object({primaryColor:q.string().describe("Primary color for the CLI theme").default("#0066cc"),accentColor:q.string().describe("Accent color for the CLI theme").default("#ff6600")}).describe("Theme configuration for the CLI interface").default({primaryColor:"#0066cc",accentColor:"#ff6600"})});var h={name:"@brains/chat-repl",license:"AGPL-3.0-only",version:"0.2.0-alpha.248",dependencies:{"@brains/plugins":"workspace:*","@brains/utils":"workspace:*",chalk:"^5.4.1",ink:"^7.0.6","ink-spinner":"^5.0.0","ink-text-input":"^6.0.0",marked:"^18.0.5",react:"^19.2.7"},devDependencies:{"@brains/eslint-config":"workspace:*","@brains/typescript-config":"workspace:*","@types/bun":"^1.3.14","@types/react":"^19.2.17",typescript:"^7.0.2"},files:["src"],main:"./src/index.ts",module:"./src/index.ts",private:!0,scripts:{dev:"tsc --watch",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",test:"bun test",typecheck:"tsc --noEmit"},type:"module",types:"./src/index.ts"};var E={completed:"\u2713",declined:"\u25CB",failed:"\u2717"};class m extends k{inkApp=null;responseCallback;agentService;signalHandler;approvalTracker;constructor(y={}){super("cli",h,y,J)}getAgentService(){if(!this.agentService)throw Error("AgentService not initialized - plugin not registered");return this.agentService}async onRegister(y){await super.onRegister(y),this.agentService=y.agent,this.logger.debug("CLI interface registered with AgentService")}sendMessageToChannel({message:y}){if(this.responseCallback)this.responseCallback(y)}registerResponseCallback(y){this.responseCallback=y}unregisterMessageCallbacks(){this.responseCallback=void 0}async onProgressUpdate(y){this.logger.debug("CLI progress update",{eventId:y.id,status:y.status,progress:y.progress,message:y.message})}createDaemon(){return{start:async()=>{if(!this.context)throw new B(this.id,"Initialization failed: Plugin context not initialized");this.logger.debug("Starting CLI interface");try{let[y,N,Q]=await Promise.all([import("./index-xr51g7y9.js"),import("./react.development-jpx27vg2.js"),import("./EnhancedApp-bg8wqynt.js")]),{render:w}=y,G=N.default,Z=Q.default,$=G.createElement(Z,{interface:this,registerProgressCallback:(W)=>this.registerProgressCallback(W),unregisterProgressCallback:()=>this.unregisterProgressCallback(),registerResponseCallback:(W)=>this.registerResponseCallback(W),unregisterMessageCallbacks:()=>this.unregisterMessageCallbacks()});this.inkApp=w($),this.registerSignalHandlers()}catch(y){throw this.logger.error("Failed to start CLI interface",{error:y}),y}},stop:async()=>{this.logger.debug("Stopping CLI interface"),await this.cleanup()},healthCheck:async()=>{let y=this.inkApp!==null;return{status:y?"healthy":"error",message:y?"CLI interface is running":"CLI interface not running",lastCheck:new Date,details:{hasInkApp:this.inkApp!==null,hasCallbacks:this.hasProgressCallback()}}}}}getApprovalTracker(){return this.approvalTracker??=new S({loadMessages:async(y)=>await this.context?.conversations.getMessages(y,{limit:50})??[],onRestoreError:(y,N)=>{this.logger.debug("Failed to restore pending CLI approvals",{error:y,conversationId:N})}}),this.approvalTracker}async getPendingApprovalIds(y){return[...await this.getApprovalTracker().getApprovalIds(y)]}async processInput(y){this.startProcessingInput();try{let Q=await this.getPendingApprovalIds("cli");if(Q.length>0){if(await this.handleConfirmationResponse(y,"cli",Q))return}let w=await this.getAgentService().chat(y,"cli",{userPermissionLevel:"admin",isAnchor:this.getContext().permissions.isAnchor("cli","local"),interfaceType:"cli",channelId:"cli",channelName:"CLI Terminal"}),G=M(w.cards),Z=G.length>0?G.map((W)=>W.id):w.pendingConfirmations?.map((W)=>W.id)??[];this.getApprovalTracker().replaceApprovals("cli",Z);let $=this.formatAgentResponseText(w.text,G);this.logger.debug("Agent response received",{textLength:w.text.length,toolResultsCount:w.toolResults?.length??0,toolResults:w.toolResults?.map((W)=>({toolName:W.toolName,hasData:W.data!==void 0}))}),this.sendMessageToChannel({channelId:null,message:$})}catch(Q){this.logger.error("Error processing input",{error:Q,input:y});let w=z(Q,"An unknown error occurred");this.sendMessageToChannel({channelId:null,message:`**Error:** ${w}`})}finally{this.endProcessingInput()}}formatAgentResponseText(y,N){if(N.length===0)return y;let Q=O(y,N);if(N.length===1){let G=N[0];if(!G)return y;let Z=G.preview?`
|
|
3
3
|
|
|
4
4
|
${G.preview}`:"";return`${Q}${Z}
|
|
5
5
|
|
|
@@ -13,5 +13,5 @@ _Please reply with **yes 1** / **no 1** for the matching action._`}formatApprova
|
|
|
13
13
|
|
|
14
14
|
${w.error}`:`${G} ${w.summary}`}parseIndexedConfirmationResponse(y){let N=/^(.*?)(?:\s+#?(\d+))?$/.exec(y.trim()),Q=N?.[1]?.trim()??y.trim(),w=P(Q);if(!w)return;let G=N?.[2];if(!G)return{confirmed:w.confirmed};return{confirmed:w.confirmed,index:Number(G)-1}}getConfirmationHelpText(y){if(y.length>1)return"_Please reply with **yes 1** / **no 1** for the matching action._";return"_Please reply with **yes** to confirm or **no/cancel** to abort._"}resolvePendingApprovalSelection(y,N){let Q=this.parseIndexedConfirmationResponse(y);if(Q===void 0)return;if(N.length>1&&Q.index===void 0){this.sendMessageToChannel({channelId:null,message:"_Multiple approvals are pending. Reply with **yes 1** / **no 1** for the matching action._"});return}let w=Q.index??0,G=N[w];if(!G){this.sendMessageToChannel({channelId:null,message:this.getConfirmationHelpText(N)});return}return{confirmed:Q.confirmed,approvalId:G}}async handleConfirmationResponse(y,N,Q){let w=this.resolvePendingApprovalSelection(y,Q);if(!w)return!1;this.getApprovalTracker().removeApproval(N,w.approvalId);let G=await this.getAgentService().confirmPendingAction(N,w.confirmed,w.approvalId,{userPermissionLevel:"admin",isAnchor:this.getContext().permissions.isAnchor("cli","local"),interfaceType:"cli"});return this.getApprovalTracker().syncFromResponse(N,G,w.approvalId),this.sendMessageToChannel({channelId:null,message:this.formatApprovalResultText(G.text,G.cards)}),!0}registerSignalHandlers(){this.signalHandler=()=>{this.logger.debug("Received termination signal, stopping CLI"),this.cleanup()},process.on("SIGINT",this.signalHandler),process.on("SIGTERM",this.signalHandler)}async cleanup(){if(this.unregisterProgressCallback(),this.unregisterMessageCallbacks(),this.signalHandler)process.removeListener("SIGINT",this.signalHandler),process.removeListener("SIGTERM",this.signalHandler),this.signalHandler=void 0;if(this.inkApp)this.inkApp.unmount(),this.inkApp=null}}var L=A(T(),1);function g({batchStatus:y,showDetails:N=!0}){let{batchId:Q,totalOperations:w,completedOperations:G,failedOperations:Z,currentOperation:$,errors:W,status:H}=y,I=H==="processing",U=H==="completed",_=H==="failed",f=G-Z;return L.jsxDEV(Y,{flexDirection:"column",marginY:1,children:[L.jsxDEV(Y,{marginBottom:1,children:L.jsxDEV(X,{bold:!0,color:"cyan",children:["Batch Operation: ",Q.slice(0,8),"..."]},void 0,!0,void 0,this)},void 0,!1,void 0,this),L.jsxDEV(Y,{marginBottom:1,children:L.jsxDEV(K,{current:G,total:w,message:"Overall Progress:",color:_?"red":U?"green":"yellow"},void 0,!1,void 0,this)},void 0,!1,void 0,this),I&&$&&L.jsxDEV(Y,{marginBottom:1,children:[L.jsxDEV(X,{color:"green",children:L.jsxDEV(C,{type:"dots"},void 0,!1,void 0,this)},void 0,!1,void 0,this),L.jsxDEV(X,{color:"gray",children:[" ",$]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),N&&L.jsxDEV(Y,{flexDirection:"column",marginLeft:2,children:[f>0&&L.jsxDEV(Y,{children:[L.jsxDEV(X,{color:"green",children:"\u2713 "},void 0,!1,void 0,this),L.jsxDEV(X,{color:"gray",children:[f," successful"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),Z>0&&L.jsxDEV(Y,{children:[L.jsxDEV(X,{color:"red",children:"\u2717 "},void 0,!1,void 0,this),L.jsxDEV(X,{color:"gray",children:[Z," failed"]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),W.length>0&&L.jsxDEV(Y,{flexDirection:"column",marginTop:1,children:[L.jsxDEV(X,{color:"red",bold:!0,children:"Errors:"},void 0,!1,void 0,this),W.slice(0,3).map((j,D)=>L.jsxDEV(Y,{marginLeft:2,children:[L.jsxDEV(X,{color:"red",children:"\u2022 "},void 0,!1,void 0,this),L.jsxDEV(X,{color:"gray",children:j},void 0,!1,void 0,this)]},D,!0,void 0,this)),W.length>3&&L.jsxDEV(Y,{marginLeft:2,children:L.jsxDEV(X,{color:"gray",children:["... and ",W.length-3," more"]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),U&&L.jsxDEV(Y,{marginTop:1,children:L.jsxDEV(X,{color:"green",bold:!0,children:"\u2713 Batch completed successfully"},void 0,!1,void 0,this)},void 0,!1,void 0,this),_&&L.jsxDEV(Y,{marginTop:1,children:L.jsxDEV(X,{color:"red",bold:!0,children:"\u2717 Batch failed"},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}export{J as cliConfigSchema,K as ProgressBar,m as CLIInterface,g as BatchProgress};
|
|
15
15
|
|
|
16
|
-
//# debugId=
|
|
17
|
-
//# sourceMappingURL=index-
|
|
16
|
+
//# debugId=FEB647F342658E0B64756E2164756E21
|
|
17
|
+
//# sourceMappingURL=index-4zsgs8gw.js.map
|
|
@@ -7,6 +7,6 @@
|
|
|
7
7
|
"/** @jsxImportSource react */\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport Spinner from \"ink-spinner\";\nimport type { BatchJobStatus } from \"@brains/job-queue\";\nimport { ProgressBar } from \"./ProgressBar\";\n\ninterface BatchProgressProps {\n batchStatus: BatchJobStatus;\n showDetails?: boolean;\n}\n\nexport function BatchProgress({\n batchStatus,\n showDetails = true,\n}: BatchProgressProps): React.ReactElement {\n const {\n batchId,\n totalOperations,\n completedOperations,\n failedOperations,\n currentOperation,\n errors,\n status,\n } = batchStatus;\n\n const inProgress = status === \"processing\";\n const isCompleted = status === \"completed\";\n const isFailed = status === \"failed\";\n\n // Calculate successful operations\n const successfulOperations = completedOperations - failedOperations;\n\n return (\n <Box flexDirection=\"column\" marginY={1}>\n {/* Header */}\n <Box marginBottom={1}>\n <Text bold color=\"cyan\">\n Batch Operation: {batchId.slice(0, 8)}...\n </Text>\n </Box>\n\n {/* Main progress bar */}\n <Box marginBottom={1}>\n <ProgressBar\n current={completedOperations}\n total={totalOperations}\n message=\"Overall Progress:\"\n color={isFailed ? \"red\" : isCompleted ? \"green\" : \"yellow\"}\n />\n </Box>\n\n {/* Current operation */}\n {inProgress && currentOperation && (\n <Box marginBottom={1}>\n <Text color=\"green\">\n <Spinner type=\"dots\" />\n </Text>\n <Text color=\"gray\"> {currentOperation}</Text>\n </Box>\n )}\n\n {/* Details section */}\n {showDetails && (\n <Box flexDirection=\"column\" marginLeft={2}>\n {/* Success count */}\n {successfulOperations > 0 && (\n <Box>\n <Text color=\"green\">✓ </Text>\n <Text color=\"gray\">{successfulOperations} successful</Text>\n </Box>\n )}\n\n {/* Failure count */}\n {failedOperations > 0 && (\n <Box>\n <Text color=\"red\">✗ </Text>\n <Text color=\"gray\">{failedOperations} failed</Text>\n </Box>\n )}\n\n {/* Errors */}\n {errors.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text color=\"red\" bold>\n Errors:\n </Text>\n {errors.slice(0, 3).map((error, index) => (\n <Box key={index} marginLeft={2}>\n <Text color=\"red\">• </Text>\n <Text color=\"gray\">{error}</Text>\n </Box>\n ))}\n {errors.length > 3 && (\n <Box marginLeft={2}>\n <Text color=\"gray\">... and {errors.length - 3} more</Text>\n </Box>\n )}\n </Box>\n )}\n </Box>\n )}\n\n {/* Final status */}\n {isCompleted && (\n <Box marginTop={1}>\n <Text color=\"green\" bold>\n ✓ Batch completed successfully\n </Text>\n </Box>\n )}\n\n {isFailed && (\n <Box marginTop={1}>\n <Text color=\"red\" bold>\n ✗ Batch failed\n </Text>\n </Box>\n )}\n </Box>\n );\n}\n"
|
|
8
8
|
],
|
|
9
9
|
"mappings": "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",
|
|
10
|
-
"debugId": "
|
|
10
|
+
"debugId": "FEB647F342658E0B64756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import{Q as W}from"./index-7hzbjwbe.js";import{pg as U}from"./index-dqm92xqk.js";import{mh as y,nh as B,oh as Z}from"./index-a6rck907.js";import{ti as a}from"./index-3dbcbegb.js";function J(t){if(t===null||typeof t!=="object"||Array.isArray(t))return!1;let b=Object.getPrototypeOf(t);return b===Object.prototype||b===null}function D(t){if(Array.isArray(t))return t.map((b)=>D(b));if(J(t))return Object.fromEntries(Object.entries(t).map(([b,w])=>[b,D(w)]));return t}var r=a.string().min(1),M=a.strictObject({member:r,value:a.record(a.string(),a.unknown()),overrides:r.optional()}),V=a.custom(J,{message:"Expected an opaque permission config object"}),l=a.strictObject({member:r,config:V,overrides:r.optional()}),N=a.strictObject({id:r,members:a.array(r),config:a.array(M).optional(),permissions:a.array(l).optional(),agentInstructions:a.array(a.string().min(1)).optional(),evalDisable:a.array(r).optional()});function H(t,b,w,x){let h=new Set;for(let[T,c]of t.entries()){if(h.has(c))x.addIssue({code:a.ZodIssueCode.custom,message:`Duplicate ${b} "${c}"`,path:[w,T]});h.add(c)}}var I=N.superRefine((t,b)=>{H(t.members,"member","members",b),H(t.evalDisable??[],"eval exclusion","evalDisable",b);let w=new Set(t.members);for(let[x,h]of(t.config??[]).entries())if(!w.has(h.member))b.addIssue({code:a.ZodIssueCode.custom,message:`Config contribution member "${h.member}" is not a member of bundle "${t.id}"`,path:["config",x,"member"]});for(let[x,h]of(t.permissions??[]).entries())if(!w.has(h.member))b.addIssue({code:a.ZodIssueCode.custom,message:`Permission contribution member "${h.member}" is not a member of bundle "${t.id}"`,path:["permissions",x,"member"]});for(let[x,h]of(t.evalDisable??[]).entries())if(!w.has(h))b.addIssue({code:a.ZodIssueCode.custom,message:`Eval exclusion member "${h}" is not a member of bundle "${t.id}"`,path:["evalDisable",x]})});function Y(t){return D(I.parse(t))}var Wa=a.array(a.string()),Ga=a.record(a.string(),a.unknown()),Za=a.unknown();var Ja=a.enum(["eval"]),$=a.enum(["person","team","organization"]);function E(t){return t}var A=a.record(a.string(),a.unknown()),Ta=a.record(a.string(),a.unknown()),S=a.enum(["eval"]),o=a.enum(["debug","info","warn","error"]),p=y,k=B,O=a.strictObject({create:k.optional(),update:k.optional(),delete:k.optional(),extract:k.optional(),publish:k.optional()}),C=a.record(a.string(),O),z=a.strictObject({package:a.string().min(1),config:a.record(a.string(),a.unknown()).optional()}),F=A.superRefine((t,b)=>{if(typeof t.package!=="string")return;if(!z.safeParse(t).success)b.addIssue({code:a.ZodIssueCode.custom,message:'external plugin declarations may only contain "package" and optional nested "config"'})}),Ma=a.strictObject({brain:a.string().optional(),anchor:$.optional(),site:a.object({package:a.string().optional(),variant:a.string().optional(),theme:a.string().optional(),themeOverride:a.string().optional()}).optional(),name:a.string().optional(),kind:a.string().trim().min(1).optional(),logLevel:o.optional(),logFile:a.string().optional(),port:a.number().optional(),domain:a.string().optional(),database:a.string().optional(),model:a.string().optional(),reasoningEffort:W.optional(),bundles:a.array(a.string().min(1)).optional(),mode:S.optional(),add:a.array(a.string()).optional(),remove:a.array(a.string()).optional(),admins:a.array(a.string()).optional(),anchors:a.array(a.string()).optional(),trusted:a.array(a.string()).optional(),spaces:a.array(a.string()).optional(),plugins:a.record(a.string(),F).optional(),permissions:a.object({admins:a.array(a.string()).optional(),anchors:a.array(a.string()).optional(),trusted:a.array(a.string()).optional(),rules:a.array(a.object({pattern:a.string(),level:p})).optional(),entityActions:C.optional()}).optional()});var oa=a.record(a.string(),a.unknown());var P=a.custom((t)=>typeof t==="function"),sa=a.looseObject({plugin:P.optional()});var s=a.strictObject({pattern:a.string(),level:y}),fa=a.strictObject({admins:a.array(a.string()).optional(),anchors:a.array(a.string()).optional(),trusted:a.array(a.string()).optional(),rules:a.array(s).optional(),entityActions:Z.optional()});var f=a.custom((t)=>U.safeParse(t).success);var n=a.looseObject({id:a.string().min(1)}),i=a.looseObject({label:a.string().min(1)}),e=a.custom((t)=>typeof t==="function"),aa=a.looseObject({layouts:a.record(a.string(),a.unknown()).optional(),plugin:e.optional(),pluginConfig:a.record(a.string(),a.unknown()).optional(),routes:a.array(n).optional(),entityDisplay:a.record(a.string(),i).optional(),content:a.unknown().optional(),themeOverride:a.string().optional(),headScripts:a.array(a.string()).optional(),staticAssets:a.record(a.string(),a.string()).optional()}),Ht=a.custom((t)=>aa.safeParse(t).success);var Pb={name:"@rizom/brain",version:"0.2.0-alpha.247",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",keywords:["brain","ai","cli","mcp","agent","personal-ai","knowledge-management"],license:"AGPL-3.0-only",author:"Yeehaa <yeehaa@rizom.ai> (https://rizom.ai)",bin:{brain:"./dist/brain.js"},bugs:"https://github.com/rizom-ai/brains/issues",dependencies:{"@clack/prompts":"^1.5.1","@modelcontextprotocol/sdk":"^1.29.0","@tailwindcss/postcss":"^4.3.1","@tailwindcss/typography":"^0.5.20",postcss:"^8.5.15",preact:"^10.27.2","preact-render-to-string":"^6.7.0",tailwindcss:"^4.3.1",yaml:"^2.9.0",zod:"^4.1.8"},devDependencies:{"@brains/a2a":"workspace:*","@brains/admin":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/ai-evaluation":"workspace:*","@brains/ai-service":"workspace:*","@brains/analytics":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/atproto":"workspace:*","@brains/atproto-registry":"workspace:*","@brains/auth-service":"workspace:*","@brains/blog":"workspace:*","@brains/build-tools":"workspace:*","@brains/chat":"workspace:*","@brains/cms":"workspace:*","@brains/content-formatters":"workspace:*","@brains/content-pipeline":"workspace:*","@brains/conversation-memory":"workspace:*","@brains/core":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/deploy-support":"workspace:*","@brains/directory-sync":"workspace:*","@brains/doc":"workspace:*","@brains/document-plugin":"workspace:*","@brains/email":"workspace:*","@brains/eslint-config":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/mcp-service":"workspace:*","@brains/newsletter":"workspace:*","@brains/note":"workspace:*","@brains/notifications":"workspace:*","@brains/obsidian-vault":"workspace:*","@brains/onboarding":"workspace:*","@brains/playbooks":"workspace:*","@brains/plugins":"workspace:*","@brains/portfolio":"workspace:*","@brains/products":"workspace:*","@brains/profile":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"workspace:*","@brains/series":"workspace:*","@brains/site-builder-plugin":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-content":"workspace:*","@brains/site-default":"workspace:*","@brains/site-info":"workspace:*","@brains/site-personal":"workspace:*","@brains/site-professional":"workspace:*","@brains/social-media":"workspace:*","@brains/stock-photo":"workspace:*","@brains/style-guide":"workspace:*","@brains/test-utils":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/topics":"workspace:*","@brains/typescript-config":"workspace:*","@brains/utils":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*","@brains/wishlist":"workspace:*","@rizom/site-rizom":"workspace:*","@rizom/theme-default":"workspace:*","@types/bun":"^1.3.14",rolldown:"^1.0.0","rolldown-plugin-dts":"^0.27.4",typescript:"^7.0.2"},engines:{bun:">=1.3.3"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./cli":"./dist/brain.js","./model":{types:"./dist/model.d.ts",import:"./dist/model.js"},"./plugins":{types:"./dist/plugins.d.ts",import:"./dist/plugins.js"},"./entities":{types:"./dist/entities.d.ts",import:"./dist/entities.js"},"./services":{types:"./dist/services.d.ts",import:"./dist/services.js"},"./interfaces":{types:"./dist/interfaces.d.ts",import:"./dist/interfaces.js"},"./templates":{types:"./dist/templates.d.ts",import:"./dist/templates.js"},"./site":{types:"./dist/site.d.ts",import:"./dist/site.js"},"./deploy":{types:"./dist/deploy.d.ts",import:"./dist/deploy.js"},"./tsconfig.instance.json":"./tsconfig.instance.json"},files:["dist","templates","tsconfig.instance.json"],homepage:"https://github.com/rizom-ai/brains/tree/main/packages/brain-cli#readme",optionalDependencies:{"@bitwarden/sdk-napi":"^1.0.0","@libsql/client":"^0.17.4","@tailwindcss/oxide":"^4.1.4",lightningcss:"^1.29.2","playwright-core":"^1.61.0","react-devtools-core":"^7.0.1",sharp:"^0.35.1"},publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/rizom-ai/brains.git",directory:"packages/brain-cli"},scripts:{build:"bun scripts/build.ts","build:ui":"turbo run build --filter=@brains/web-chat --filter=@brains/cms --filter=@brains/admin","dev:start":"bun scripts/build.ts && bun dist/brain.js start",eval:"brain-eval","eval:core":"brain-eval --suite core","eval:personal":"brain-eval --suite personal","eval:publishing":"brain-eval --suite publishing","eval:team":"brain-eval --suite team","eval:commerce":"brain-eval --suite commerce",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",prepublishOnly:"bun scripts/build.ts","start:minimal":"bun run build:ui && cd test-apps/minimal && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:personal":"bun run build:ui && cd test-apps/personal && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:publishing":"bun run build:ui && cd test-apps/publishing && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:team":"bun run build:ui && cd test-apps/team && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p tsconfig.model.json"},type:"module"};
|
|
3
|
-
export{
|
|
2
|
+
import{Q as G}from"./index-wnkz9tp7.js";import{pg as U}from"./index-dqm92xqk.js";import{mh as y,nh as W,oh as X}from"./index-a6rck907.js";import{ti as a}from"./index-3dbcbegb.js";function F(t){if(t===null||typeof t!=="object"||Array.isArray(t))return!1;let b=Object.getPrototypeOf(t);return b===Object.prototype||b===null}function $(t){if(Array.isArray(t))return t.map((b)=>$(b));if(F(t))return Object.fromEntries(Object.entries(t).map(([b,w])=>[b,$(w)]));return t}var r=a.string().min(1),V=a.strictObject({member:r,value:a.record(a.string(),a.unknown()),overrides:r.optional()}),N=a.custom(F,{message:"Expected an opaque permission config object"}),I=a.strictObject({member:r,config:N,overrides:r.optional()}),E=a.strictObject({id:r,members:a.array(r),config:a.array(V).optional(),permissions:a.array(I).optional(),agentInstructions:a.array(a.string().min(1)).optional(),evalDisable:a.array(r).optional()});function z(t,b,w,x){let h=new Set;for(let[M,D]of t.entries()){if(h.has(D))x.addIssue({code:a.ZodIssueCode.custom,message:`Duplicate ${b} "${D}"`,path:[w,M]});h.add(D)}}var A=E.superRefine((t,b)=>{z(t.members,"member","members",b),z(t.evalDisable??[],"eval exclusion","evalDisable",b);let w=new Set(t.members);for(let[x,h]of(t.config??[]).entries())if(!w.has(h.member))b.addIssue({code:a.ZodIssueCode.custom,message:`Config contribution member "${h.member}" is not a member of bundle "${t.id}"`,path:["config",x,"member"]});for(let[x,h]of(t.permissions??[]).entries())if(!w.has(h.member))b.addIssue({code:a.ZodIssueCode.custom,message:`Permission contribution member "${h.member}" is not a member of bundle "${t.id}"`,path:["permissions",x,"member"]});for(let[x,h]of(t.evalDisable??[]).entries())if(!w.has(h))b.addIssue({code:a.ZodIssueCode.custom,message:`Eval exclusion member "${h}" is not a member of bundle "${t.id}"`,path:["evalDisable",x]})});function c(t){return $(A.parse(t))}var Ga=a.array(a.string()),Za=a.record(a.string(),a.unknown()),Qa=a.unknown();var Ya=a.enum(["eval"]),B=a.enum(["person","team","organization"]);function S(t){return t}var l=a.record(a.string(),a.unknown()),Ta=a.record(a.string(),a.unknown()),O=a.enum(["eval"]),p=a.enum(["debug","info","warn","error"]),o=y,k=W,C=a.strictObject({create:k.optional(),update:k.optional(),delete:k.optional(),extract:k.optional(),publish:k.optional()}),P=a.record(a.string(),C),m=a.strictObject({package:a.string().min(1),config:a.record(a.string(),a.unknown()).optional()}),K=l.superRefine((t,b)=>{if(typeof t.package!=="string")return;if(!m.safeParse(t).success)b.addIssue({code:a.ZodIssueCode.custom,message:'external plugin declarations may only contain "package" and optional nested "config"'})}),Ma=a.strictObject({brain:a.string().optional(),anchor:B.optional(),site:a.object({package:a.string().optional(),variant:a.string().optional(),theme:a.string().optional(),themeOverride:a.string().optional()}).optional(),name:a.string().optional(),kind:a.string().trim().min(1).optional(),logLevel:p.optional(),logFile:a.string().optional(),port:a.number().optional(),domain:a.string().optional(),database:a.string().optional(),model:a.string().optional(),reasoningEffort:G.optional(),bundles:a.array(a.string().min(1)).optional(),mode:O.optional(),add:a.array(a.string()).optional(),remove:a.array(a.string()).optional(),admins:a.array(a.string()).optional(),anchors:a.array(a.string()).optional(),trusted:a.array(a.string()).optional(),spaces:a.array(a.string()).optional(),plugins:a.record(a.string(),K).optional(),permissions:a.object({admins:a.array(a.string()).optional(),anchors:a.array(a.string()).optional(),trusted:a.array(a.string()).optional(),rules:a.array(a.object({pattern:a.string(),level:o})).optional(),entityActions:P.optional()}).optional()});var Oa=a.record(a.string(),a.unknown());var s=a.custom((t)=>typeof t==="function"),sa=a.looseObject({plugin:s.optional()});var g=a.strictObject({pattern:a.string(),level:y}),fa=a.strictObject({admins:a.array(a.string()).optional(),anchors:a.array(a.string()).optional(),trusted:a.array(a.string()).optional(),rules:a.array(g).optional(),entityActions:X.optional()});var q=a.custom((t)=>U.safeParse(t).success);var n=a.looseObject({id:a.string().min(1)}),i=a.looseObject({label:a.string().min(1)}),e=a.custom((t)=>typeof t==="function"),aa=a.looseObject({layouts:a.record(a.string(),a.unknown()).optional(),plugin:e.optional(),pluginConfig:a.record(a.string(),a.unknown()).optional(),routes:a.array(n).optional(),entityDisplay:a.record(a.string(),i).optional(),content:a.unknown().optional(),themeOverride:a.string().optional(),headScripts:a.array(a.string()).optional(),staticAssets:a.record(a.string(),a.string()).optional()}),Jt=a.custom((t)=>aa.safeParse(t).success);var gb={name:"@rizom/brain",version:"0.2.0-alpha.248",description:"Brain runtime + CLI \u2014 scaffold, run, and manage AI brain instances",keywords:["brain","ai","cli","mcp","agent","personal-ai","knowledge-management"],license:"AGPL-3.0-only",author:"Yeehaa <yeehaa@rizom.ai> (https://rizom.ai)",bin:{brain:"./dist/brain.js"},bugs:"https://github.com/rizom-ai/brains/issues",dependencies:{"@clack/prompts":"^1.5.1","@modelcontextprotocol/sdk":"^1.29.0","@tailwindcss/postcss":"^4.3.1","@tailwindcss/typography":"^0.5.20",postcss:"^8.5.15",preact:"^10.27.2","preact-render-to-string":"^6.7.0",tailwindcss:"^4.3.1",yaml:"^2.9.0",zod:"^4.1.8"},devDependencies:{"@brains/a2a":"workspace:*","@brains/admin":"workspace:*","@brains/agent-discovery":"workspace:*","@brains/ai-evaluation":"workspace:*","@brains/ai-service":"workspace:*","@brains/analytics":"workspace:*","@brains/app":"workspace:*","@brains/assessment":"workspace:*","@brains/atproto":"workspace:*","@brains/atproto-registry":"workspace:*","@brains/auth-service":"workspace:*","@brains/blog":"workspace:*","@brains/build-tools":"workspace:*","@brains/chat":"workspace:*","@brains/cms":"workspace:*","@brains/content-formatters":"workspace:*","@brains/content-pipeline":"workspace:*","@brains/conversation-memory":"workspace:*","@brains/core":"workspace:*","@brains/dashboard":"workspace:*","@brains/decks":"workspace:*","@brains/deploy-support":"workspace:*","@brains/directory-sync":"workspace:*","@brains/doc":"workspace:*","@brains/document-plugin":"workspace:*","@brains/email":"workspace:*","@brains/eslint-config":"workspace:*","@brains/image-plugin":"workspace:*","@brains/link":"workspace:*","@brains/mcp":"workspace:*","@brains/mcp-service":"workspace:*","@brains/newsletter":"workspace:*","@brains/note":"workspace:*","@brains/notifications":"workspace:*","@brains/obsidian-vault":"workspace:*","@brains/onboarding":"workspace:*","@brains/playbooks":"workspace:*","@brains/plugins":"workspace:*","@brains/portfolio":"workspace:*","@brains/products":"workspace:*","@brains/profile":"workspace:*","@brains/prompt":"workspace:*","@brains/rizom-ecosystem":"workspace:*","@brains/series":"workspace:*","@brains/site-builder-plugin":"workspace:*","@brains/site-composition":"workspace:*","@brains/site-content":"workspace:*","@brains/site-default":"workspace:*","@brains/site-info":"workspace:*","@brains/site-personal":"workspace:*","@brains/site-professional":"workspace:*","@brains/social-media":"workspace:*","@brains/stock-photo":"workspace:*","@brains/style-guide":"workspace:*","@brains/test-utils":"workspace:*","@brains/theme-rizom":"workspace:*","@brains/topics":"workspace:*","@brains/typescript-config":"workspace:*","@brains/utils":"workspace:*","@brains/web-chat":"workspace:*","@brains/webserver":"workspace:*","@brains/wishlist":"workspace:*","@rizom/site-rizom":"workspace:*","@rizom/theme-default":"workspace:*","@types/bun":"^1.3.14",rolldown:"^1.0.0","rolldown-plugin-dts":"^0.27.4",typescript:"^7.0.2"},engines:{bun:">=1.3.3"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./cli":"./dist/brain.js","./model":{types:"./dist/model.d.ts",import:"./dist/model.js"},"./plugins":{types:"./dist/plugins.d.ts",import:"./dist/plugins.js"},"./entities":{types:"./dist/entities.d.ts",import:"./dist/entities.js"},"./services":{types:"./dist/services.d.ts",import:"./dist/services.js"},"./interfaces":{types:"./dist/interfaces.d.ts",import:"./dist/interfaces.js"},"./templates":{types:"./dist/templates.d.ts",import:"./dist/templates.js"},"./site":{types:"./dist/site.d.ts",import:"./dist/site.js"},"./deploy":{types:"./dist/deploy.d.ts",import:"./dist/deploy.js"},"./tsconfig.instance.json":"./tsconfig.instance.json"},files:["dist","templates","tsconfig.instance.json"],homepage:"https://github.com/rizom-ai/brains/tree/main/packages/brain-cli#readme",optionalDependencies:{"@bitwarden/sdk-napi":"^1.0.0","@libsql/client":"^0.17.4","@tailwindcss/oxide":"^4.1.4",lightningcss:"^1.29.2","playwright-core":"^1.61.0","react-devtools-core":"^7.0.1",sharp:"^0.35.1"},publishConfig:{access:"public"},repository:{type:"git",url:"https://github.com/rizom-ai/brains.git",directory:"packages/brain-cli"},scripts:{build:"bun scripts/build.ts","build:ui":"turbo run build --filter=@brains/web-chat --filter=@brains/cms --filter=@brains/admin","dev:start":"bun scripts/build.ts && bun dist/brain.js start",eval:"brain-eval","eval:core":"brain-eval --suite core","eval:personal":"brain-eval --suite personal","eval:publishing":"brain-eval --suite publishing","eval:team":"brain-eval --suite team","eval:commerce":"brain-eval --suite commerce",lint:"eslint . --max-warnings 0","lint:fix":"eslint . --max-warnings 0 --fix",prepublishOnly:"bun scripts/build.ts","start:minimal":"bun run build:ui && cd test-apps/minimal && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:personal":"bun run build:ui && cd test-apps/personal && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:publishing":"bun run build:ui && cd test-apps/publishing && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start","start:team":"bun run build:ui && cd test-apps/team && INIT_CWD=$PWD bun run $([ -t 1 ] && echo --elide-lines=0) --filter @rizom/brain dev:start",test:"bun test",typecheck:"tsc --noEmit && tsc --noEmit -p tsconfig.model.json"},type:"module"};
|
|
3
|
+
export{S as F,c as G,gb as H};
|
|
4
4
|
|
|
5
|
-
//# debugId=
|
|
6
|
-
//# sourceMappingURL=index-
|
|
5
|
+
//# debugId=6A849ADF7E0345A464756E2164756E21
|
|
6
|
+
//# sourceMappingURL=index-67b6py9k.js.map
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"import type { PermissionConfig } from \"@brains/templates\";\nimport { z } from \"@brains/utils/zod\";\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value) as unknown;\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction cloneValue<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map((item) => cloneValue(item)) as T;\n }\n\n if (isPlainRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, cloneValue(item)]),\n ) as T;\n }\n\n return value;\n}\n\nexport interface BundleConfigContribution {\n member: string;\n value: Record<string, unknown>;\n overrides?: string | undefined;\n}\n\nexport interface BundlePermissionContribution {\n member: string;\n config: PermissionConfig;\n overrides?: string | undefined;\n}\n\nexport interface CapabilityBundleDefinition {\n id: string;\n members: string[];\n config?: BundleConfigContribution[] | undefined;\n permissions?: BundlePermissionContribution[] | undefined;\n agentInstructions?: string[] | undefined;\n evalDisable?: string[] | undefined;\n}\n\nconst bundleIdSchema = z.string().min(1);\n\nexport const bundleConfigContributionSchema: z.ZodType<BundleConfigContribution> =\n z.strictObject({\n member: bundleIdSchema,\n value: z.record(z.string(), z.unknown()),\n overrides: bundleIdSchema.optional(),\n });\n\nconst opaquePermissionConfigSchema = z.custom<PermissionConfig>(isPlainRecord, {\n message: \"Expected an opaque permission config object\",\n});\n\nexport const bundlePermissionContributionSchema: z.ZodType<BundlePermissionContribution> =\n z.strictObject({\n member: bundleIdSchema,\n config: opaquePermissionConfigSchema,\n overrides: bundleIdSchema.optional(),\n });\n\nconst rawCapabilityBundleDefinitionSchema: z.ZodType<CapabilityBundleDefinition> =\n z.strictObject({\n id: bundleIdSchema,\n members: z.array(bundleIdSchema),\n config: z.array(bundleConfigContributionSchema).optional(),\n permissions: z.array(bundlePermissionContributionSchema).optional(),\n agentInstructions: z.array(z.string().min(1)).optional(),\n evalDisable: z.array(bundleIdSchema).optional(),\n });\n\nfunction addDuplicateIssues(\n values: readonly string[],\n label: string,\n path: string,\n ctx: z.RefinementCtx,\n): void {\n const seen = new Set<string>();\n for (const [index, value] of values.entries()) {\n if (seen.has(value)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Duplicate ${label} \"${value}\"`,\n path: [path, index],\n });\n }\n seen.add(value);\n }\n}\n\nexport const capabilityBundleDefinitionSchema: z.ZodType<CapabilityBundleDefinition> =\n rawCapabilityBundleDefinitionSchema.superRefine((definition, ctx) => {\n addDuplicateIssues(definition.members, \"member\", \"members\", ctx);\n addDuplicateIssues(\n definition.evalDisable ?? [],\n \"eval exclusion\",\n \"evalDisable\",\n ctx,\n );\n\n const members = new Set(definition.members);\n for (const [index, contribution] of (definition.config ?? []).entries()) {\n if (!members.has(contribution.member)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Config contribution member \"${contribution.member}\" is not a member of bundle \"${definition.id}\"`,\n path: [\"config\", index, \"member\"],\n });\n }\n }\n\n for (const [index, contribution] of (\n definition.permissions ?? []\n ).entries()) {\n if (!members.has(contribution.member)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Permission contribution member \"${contribution.member}\" is not a member of bundle \"${definition.id}\"`,\n path: [\"permissions\", index, \"member\"],\n });\n }\n }\n\n for (const [index, member] of (definition.evalDisable ?? []).entries()) {\n if (!members.has(member)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Eval exclusion member \"${member}\" is not a member of bundle \"${definition.id}\"`,\n path: [\"evalDisable\", index],\n });\n }\n }\n });\n\n/** Validate bundle data without constructing any plugins or runtime resources. */\nexport function defineBundle(\n definition: CapabilityBundleDefinition,\n): CapabilityBundleDefinition {\n return cloneValue(capabilityBundleDefinitionSchema.parse(definition));\n}\n",
|
|
6
6
|
"import { z } from \"@brains/utils/zod\";\nimport type { AppConfig } from \"./types\";\nimport type { App as AppClass } from \"./app\";\nimport type { ActorRef } from \"@brains/contracts\";\nimport type { ToolResponse } from \"@brains/mcp-service\";\nimport { getErrorMessage } from \"@brains/utils/error\";\n\ninterface AppFactory {\n create: typeof AppClass.create;\n}\n\ntype InitializeOptions = Parameters<\n ReturnType<typeof AppClass.create>[\"initialize\"]\n>[0];\n\nfunction getArgValue(args: string[], flag: string): string | undefined {\n const flagIdx = args.indexOf(flag);\n return flagIdx !== -1 ? args[flagIdx + 1] : undefined;\n}\n\nfunction requireArgValue(\n args: string[],\n flag: string,\n message: string,\n): string {\n const value = getArgValue(args, flag);\n if (value === undefined) {\n console.error(message);\n process.exit(1);\n }\n return value;\n}\n\ninterface JsonFlagSchema<T> {\n parse(value: unknown): T;\n}\n\nconst cliArgsSchema = z.array(z.string());\nconst cliFlagsSchema = z.record(z.string(), z.unknown());\nconst jsonValueSchema = z.unknown();\n\nfunction parseJsonFlag<T>(\n args: string[],\n flag: string,\n defaultValue: T,\n schema: JsonFlagSchema<T>,\n): T {\n const value = getArgValue(args, flag);\n return value ? schema.parse(JSON.parse(value)) : defaultValue;\n}\n\nfunction createHeadlessConfig(config: AppConfig): AppConfig {\n return {\n ...config,\n plugins: (config.plugins ?? []).filter((p) => p.type !== \"interface\"),\n };\n}\n\nasync function routeLogsToStderr(): Promise<void> {\n const { Logger } = await import(\"@brains/utils/logger\");\n Logger.getInstance().setUseStderr(true);\n}\n\nasync function initializeHeadlessApp(\n config: AppConfig,\n App: AppFactory,\n options?: InitializeOptions,\n): Promise<ReturnType<typeof AppClass.create>> {\n await routeLogsToStderr();\n\n const app = App.create(createHeadlessConfig(config));\n await app.initialize(options);\n return app;\n}\n\nfunction printToolResult(result: ToolResponse): void {\n if (\"needsConfirmation\" in result) {\n const detail = result.preview ? `\\n\\n${result.preview}` : \"\";\n console.log(`Confirmation needed: ${result.summary}${detail}`);\n process.exit(0);\n }\n\n if (!result.success) {\n console.error(`❌ ${result.error}`);\n process.exit(1);\n }\n\n if (result.message) {\n console.log(result.message);\n }\n if (result.data !== undefined) {\n console.log(\n typeof result.data === \"string\"\n ? result.data\n : JSON.stringify(result.data, null, 2),\n );\n }\n}\n\nasync function invokeCliTool(\n handler: (\n input: unknown,\n context: { interfaceType: string; actor: ActorRef },\n ) => Promise<ToolResponse>,\n input: unknown,\n failureLabel: string,\n): Promise<void> {\n try {\n const result = await handler(input, {\n interfaceType: \"cli\",\n actor: { kind: \"service\", serviceId: \"shell-cli\" },\n });\n printToolResult(result);\n } catch (error) {\n console.error(`❌ ${failureLabel} failed:`, getErrorMessage(error));\n process.exit(1);\n }\n}\n\n/**\n * Export deployment config as JSON for shell scripts\n * This is used by deploy scripts to extract config without starting the app\n */\nfunction exportDeployConfig(config: AppConfig): void {\n const deployment = config.deployment;\n\n const deployConfig = {\n name: config.name,\n version: config.version,\n // Server\n provider: deployment.provider,\n serverSize: deployment.serverSize,\n location: deployment.location,\n domain: deployment.domain,\n // Docker\n docker: {\n enabled: deployment.docker.enabled,\n image: deployment.docker.image ?? config.name,\n },\n // Ports\n ports: {\n default: deployment.ports.default,\n preview: deployment.ports.preview,\n production: deployment.ports.production,\n },\n // CDN\n cdn: {\n enabled: deployment.cdn.enabled,\n provider: deployment.cdn.provider,\n },\n // DNS\n dns: {\n enabled: deployment.dns.enabled,\n provider: deployment.dns.provider,\n },\n // Paths (compute defaults based on app name)\n paths: {\n install: deployment.paths.install ?? `/opt/${config.name}`,\n data: deployment.paths.data ?? `/opt/${config.name}/data`,\n },\n };\n\n console.log(JSON.stringify(deployConfig, null, 2));\n process.exit(0);\n}\n\n/**\n * Handle CLI arguments and run appropriate commands from a generated brain entrypoint.\n */\nexport async function handleCLI(config: AppConfig): Promise<void> {\n const args = process.argv.slice(2);\n\n // Handle --export-deploy-config first (no app startup needed)\n if (args.includes(\"--export-deploy-config\")) {\n exportDeployConfig(config);\n return; // exportDeployConfig calls process.exit\n }\n\n // Set up error handling\n process.on(\"uncaughtException\", (error) => {\n console.error(`❌ ${config.name} crashed:`, error);\n process.exit(1);\n });\n\n process.on(\"unhandledRejection\", (reason) => {\n console.error(`❌ ${config.name} unhandled rejection:`, reason);\n process.exit(1);\n });\n\n // Dynamically import App to avoid circular dependency\n const { App } = await import(\"./app\");\n\n // Handle CLI commands\n if (args.includes(\"--help\") || args.includes(\"-h\")) {\n showHelp(config);\n } else if (args.includes(\"--version\") || args.includes(\"-v\")) {\n console.log(`${config.name} v${config.version}`);\n process.exit(0);\n } else if (args.includes(\"--startup-check\")) {\n // Startup check: register plugins and run ready hooks, but do not start\n // daemons or job workers. Used by external plugin smoke tests.\n const app = App.create(config);\n await app.initialize({ mode: \"startup-check\" });\n await app.stop();\n } else if (args.includes(\"--list-cli-commands\")) {\n // List CLI-enabled tools for dynamic help\n await listCliCommands(config, App);\n } else if (args[0] === \"diagnostics\") {\n // Diagnostics mode: boot brain, run diagnostics, exit\n await runDiagnostics(config, args.slice(1), App);\n } else if (args.includes(\"--cli-command\")) {\n // Headless mode via CLI command name: boot, find tool by cli.name, invoke, exit\n await runCliCommand(config, args, App);\n } else if (args.includes(\"--tool\")) {\n // Raw tool invocation: boot, invoke by full tool name, exit\n await runTool(config, args, App);\n } else {\n // Default: run the app\n console.log(`🚀 Starting ${config.name} v${config.version}...`);\n App.run(config).catch((error) => {\n console.error(`❌ Failed to start ${config.name}:`, error);\n process.exit(1);\n });\n }\n}\n\n/**\n * List all CLI-enabled tools. Used by brain --help to discover available commands.\n */\nasync function listCliCommands(\n config: AppConfig,\n App: AppFactory,\n): Promise<void> {\n const app = await initializeHeadlessApp(config, App, {\n mode: \"register-only\",\n });\n\n const cliTools = app.getShell().getMCPService().getCliTools();\n for (const { tool } of cliTools) {\n if (tool.cli) {\n console.log(`${tool.cli.name.padEnd(16)}${tool.description}`);\n }\n }\n\n process.exit(0);\n}\n\n/**\n * Headless mode via CLI command name: boot brain, find tool by cli.name, invoke, exit.\n *\n * Used by `brain list`, `brain sync`, etc. The brain CLI passes the command\n * name and args/flags as JSON. This function discovers the matching tool\n * via getCliTools() and invokes it.\n */\nasync function runCliCommand(\n config: AppConfig,\n args: string[],\n App: AppFactory,\n): Promise<void> {\n const commandName = requireArgValue(\n args,\n \"--cli-command\",\n \"❌ --cli-command requires a command name\",\n );\n const cliArgs = parseJsonFlag(args, \"--cli-args\", [], cliArgsSchema);\n const cliFlags = parseJsonFlag(args, \"--cli-flags\", {}, cliFlagsSchema);\n\n const app = await initializeHeadlessApp(config, App);\n const cliTools = app.getShell().getMCPService().getCliTools();\n const match = cliTools.find((t) => t.tool.cli?.name === commandName);\n\n if (!match?.tool.cli) {\n const available = cliTools\n .map((t) => t.tool.cli?.name)\n .filter(Boolean)\n .join(\", \");\n console.error(`❌ Unknown command: ${commandName}`);\n console.error(`Available commands: ${available}`);\n process.exit(1);\n }\n\n const { mapArgsToInput } = await import(\"@brains/mcp-service\");\n const toolInput = mapArgsToInput(match.tool.inputSchema, cliArgs, cliFlags);\n await invokeCliTool(match.tool.handler, toolInput, `Command ${commandName}`);\n\n process.exit(0);\n}\n\n/**\n * Headless mode: boot brain without daemons, invoke a tool, print result, exit.\n *\n * Used by `brain list`, `brain get`, `brain sync`, etc.\n * Skips all interface plugins (MCP, Discord, webserver) — only loads\n * entity plugins and service plugins.\n */\nasync function runTool(\n config: AppConfig,\n args: string[],\n App: AppFactory,\n): Promise<void> {\n const toolName = requireArgValue(\n args,\n \"--tool\",\n \"❌ --tool requires a tool name\",\n );\n\n let toolInput: unknown = {};\n try {\n toolInput = parseJsonFlag(args, \"--tool-input\", {}, jsonValueSchema);\n } catch {\n console.error(\"❌ --tool-input must be valid JSON\");\n process.exit(1);\n }\n\n const app = await initializeHeadlessApp(config, App);\n const tools = app.getShell().getMCPService().listTools();\n const match = tools.find((t) => t.tool.name === toolName);\n\n if (!match) {\n console.error(`❌ Tool not found: ${toolName}`);\n console.error(\n `Available tools: ${tools.map((t) => t.tool.name).join(\", \")}`,\n );\n process.exit(1);\n }\n\n await invokeCliTool(match.tool.handler, toolInput, `Tool ${toolName}`);\n\n process.exit(0);\n}\n\n/**\n * Run diagnostics: boot brain (full, with daemons disabled), analyze, exit.\n */\nasync function runDiagnostics(\n config: AppConfig,\n args: string[],\n App: AppFactory,\n): Promise<void> {\n const { Logger, LogLevel } = await import(\"@brains/utils/logger\");\n // Suppress plugin registration noise — only show warnings and errors\n Logger.resetInstance();\n Logger.getInstance({ level: LogLevel.WARN, useStderr: true });\n\n const subcommand = args[0] ?? \"\";\n\n if (subcommand === \"usage\") {\n await runUsageDiagnostics(config);\n return;\n }\n\n if (subcommand !== \"search\") {\n console.error(\"Usage: brain diagnostics <search|usage>\");\n process.exit(1);\n }\n\n // Boot in register-only mode — no daemons, no sync, no builds.\n // We only need access to the existing entity + embedding data.\n const app = App.create(createHeadlessConfig(config));\n await app.initialize({ mode: \"register-only\" });\n\n const shell = app.getShell();\n const entityService = shell.getEntityService();\n await entityService.initialize();\n\n const entityTypes = entityService.getEntityTypes();\n const allEntities: Array<{ id: string; entityType: string; title: string }> =\n [];\n\n const entityLists = await Promise.all(\n entityTypes.map((type) =>\n entityService.listEntities({\n entityType: type,\n options: { limit: 100 },\n }),\n ),\n );\n for (const entities of entityLists) {\n for (const entity of entities) {\n const meta = cliFlagsSchema.parse(entity.metadata);\n const title = String(meta[\"title\"] ?? meta[\"name\"] ?? entity.id);\n allEntities.push({ id: entity.id, entityType: entity.entityType, title });\n }\n }\n\n if (allEntities.length === 0) {\n await shell.shutdown();\n console.error(\"No entities found\");\n process.exit(1);\n }\n\n console.log(`\\nAnalyzing ${allEntities.length} entities...\\n`);\n\n const sampleSize = Math.min(20, allEntities.length);\n const samples = allEntities\n .sort(() => Math.random() - 0.5)\n .slice(0, sampleSize);\n\n const allDistances: number[] = [];\n const selfDistances: number[] = [];\n\n const searchResults = await Promise.all(\n samples.map((s) => entityService.searchWithDistances({ query: s.title })),\n );\n for (const [i, sample] of samples.entries()) {\n for (const r of searchResults[i] ?? []) {\n allDistances.push(r.distance);\n if (r.entityId === sample.id && r.entityType === sample.entityType) {\n selfDistances.push(r.distance);\n }\n }\n }\n\n allDistances.sort((a, b) => a - b);\n selfDistances.sort((a, b) => a - b);\n\n const pct = (arr: number[], p: number): number => {\n if (arr.length === 0) return 0;\n const idx = Math.ceil((p / 100) * arr.length) - 1;\n return arr[Math.max(0, idx)] ?? 0;\n };\n\n console.log(\"=== Search Distance Distribution ===\\n\");\n console.log(`Queries sampled: ${samples.length}`);\n console.log(`Total distance measurements: ${allDistances.length}`);\n console.log(`Self-match distances: ${selfDistances.length}\\n`);\n\n console.log(\"All distances:\");\n for (const p of [0, 25, 50, 75, 90, 95, 100]) {\n const label = p === 0 ? \"min\" : p === 100 ? \"max\" : `p${p}`;\n console.log(` ${label.padEnd(5)} ${pct(allDistances, p).toFixed(4)}`);\n }\n\n console.log(\"\\nSelf-match distances (query = entity title):\");\n console.log(` min: ${pct(selfDistances, 0).toFixed(4)}`);\n console.log(` p50: ${pct(selfDistances, 50).toFixed(4)}`);\n console.log(` max: ${pct(selfDistances, 100).toFixed(4)}\\n`);\n\n const p75 = pct(allDistances, 75);\n const p90 = pct(allDistances, 90);\n const suggested = Number(((p75 + p90) / 2).toFixed(4));\n\n console.log(`Current threshold: 0.82`);\n console.log(`Suggested threshold: ${suggested}`);\n console.log(\n ` (midpoint between p75=${p75.toFixed(4)} and p90=${p90.toFixed(4)})\\n`,\n );\n\n await shell.shutdown();\n process.exit(0);\n}\n\n/**\n * Run usage diagnostics: read the log file, aggregate ai:usage events.\n */\nasync function runUsageDiagnostics(config: AppConfig): Promise<void> {\n const logFile = config.logFile;\n if (!logFile) {\n console.error(\n \"No log file configured. Set logFile in brain.yaml to enable usage tracking.\",\n );\n process.exit(1);\n }\n\n const { existsSync, readFileSync } = await import(\"node:fs\");\n if (!existsSync(logFile)) {\n console.error(`Log file not found: ${logFile}`);\n process.exit(1);\n }\n\n const { aggregateUsage } = await import(\"./usage-aggregator\");\n const content = readFileSync(logFile, \"utf-8\");\n const report = aggregateUsage(content);\n\n if (report.events.length === 0) {\n console.log(\"No ai:usage events found in log file.\");\n process.exit(0);\n }\n\n const total = report.totalInputTokens + report.totalOutputTokens;\n\n console.log(\"=== AI Usage ===\\n\");\n console.log(`Period: ${report.firstTs} → ${report.lastTs}`);\n console.log(`Total events: ${report.events.length}`);\n console.log(\n `Total input tokens: ${report.totalInputTokens.toLocaleString()}`,\n );\n console.log(\n `Total output tokens: ${report.totalOutputTokens.toLocaleString()}`,\n );\n console.log(`Total tokens: ${total.toLocaleString()}\\n`);\n\n console.log(\"By model:\");\n for (const [key, agg] of report.byModel.entries()) {\n console.log(\n ` ${key.padEnd(40)} ${String(agg.calls).padStart(5)} calls, ` +\n `${agg.inputTokens.toLocaleString().padStart(12)} in, ` +\n `${agg.outputTokens.toLocaleString().padStart(12)} out`,\n );\n }\n\n process.exit(0);\n}\n\n/**\n * Show help information\n */\nfunction showHelp(config: AppConfig): void {\n console.log(`\n${config.name} v${config.version}\n\nUsage:\n brains [options]\n\nOptions:\n --help, -h Show this help message\n --version, -v Show version information\n --cli Enable CLI interface (passed to app)\n --export-deploy-config Export deployment config as JSON (for deploy scripts)\n\nExamples:\n brains # Start the app\n brains --cli # Start with CLI interface\n brains --export-deploy-config # Output deployment JSON\n`);\n process.exit(0);\n}\n",
|
|
7
7
|
"import type { Plugin } from \"@brains/plugins\";\nimport type { PermissionConfig } from \"@brains/templates\";\nimport type { DeploymentConfigInput, ReasoningEffort } from \"./types\";\nimport type { SitePackage } from \"./site-package\";\nimport type { CapabilityBundleDefinition } from \"./bundle-definition\";\n\nimport { z } from \"@brains/utils/zod\";\n\nexport const modeSchema: z.ZodEnum<{ eval: \"eval\" }> = z.enum([\"eval\"]);\nexport type BrainMode = z.output<typeof modeSchema>;\n\nexport const brainAnchorConfigKindSchema: z.ZodEnum<{\n person: \"person\";\n team: \"team\";\n organization: \"organization\";\n}> = z.enum([\"person\", \"team\", \"organization\"]);\nexport type BrainAnchorConfigKind = z.output<\n typeof brainAnchorConfigKindSchema\n>;\n\n/**\n * Environment record — the deployment-specific variables\n * passed to interface env mappers and the resolver.\n */\nexport type BrainEnvironment = Record<string, string | undefined>;\n\n/** Plugin config objects — always key/value records. */\nexport type PluginConfig = Record<string, unknown>;\n\n/**\n * A capability is an [id, factory, config] tuple.\n * The id is used for disable checks and override matching in brain.yaml.\n * The factory is called with the config at resolve time to create a fresh plugin instance.\n *\n * Config can be:\n * - A static value (passed directly to the factory)\n * - A function `(env, context) => config` that receives the deployment environment\n * and active bundle context (use this when the plugin needs credentials,\n * bundle-specific values, or other env-specific settings)\n * - undefined (plugin uses its own defaults)\n */\nexport interface CapabilityContext {\n bundles: readonly string[];\n}\n\nexport type CapabilityConfig =\n | PluginConfig\n | ((env: BrainEnvironment, context: CapabilityContext) => PluginConfig)\n | undefined;\n\n/**\n * A plugin factory builds one plugin or — for composite features that bundle\n * an entity + service pair behind one shared config (e.g. newsletter +\n * buttondown) — an array of plugins. Composite sub-plugins are gated as a\n * unit by the capability id; add or remove the entry from a bundle to\n * enable/disable all of them.\n */\nexport type PluginFactory = (config: PluginConfig) => Plugin | Plugin[];\n\nexport type CapabilityEntry = [\n id: string,\n factory: PluginFactory,\n config: CapabilityConfig,\n];\n\n/**\n * An interface entry is an [id, constructor, envMapper] tuple.\n * The id is used for disable checks and override matching in brain.yaml.\n * The envMapper receives the deployment environment and returns the interface config,\n * or null to skip this interface (e.g. when credentials are missing).\n * The constructor is called with `new` to create a fresh interface instance.\n */\nexport type InterfaceConstructor = new (config: PluginConfig) => Plugin;\n\nexport type InterfaceEntry = [\n id: string,\n constructor: InterfaceConstructor,\n envMapper: (env: BrainEnvironment) => PluginConfig | null,\n];\n\n/**\n * Brain identity — who this brain is.\n * Pure data, no code references.\n */\nexport interface BrainIdentity {\n characterName: string;\n role: string;\n purpose: string;\n values: string[];\n}\n\n/**\n * The brain definition — a reusable model that describes what a brain IS.\n *\n * Key design principles:\n * - No `process.env` — environment is injected at resolve time\n * - Capabilities are [id, factory, config] tuples, not instantiated plugins\n * - Interfaces are [id, constructor, envMapper] tuples\n * - Identity, permissions, content model, deployment are pure data\n * - Can be instantiated multiple times with different environments\n */\nexport interface BrainDefinition {\n /** Brain name (used as app name) */\n name: string;\n /** Semantic version */\n version: string;\n\n /**\n * Default Anchor profile flavor. Instances may override this in brain.yaml.\n * Team and organization are both collective ownership mechanically.\n */\n anchor?: BrainAnchorConfigKind;\n\n /**\n * Default semantic profile kind selected from the composed catalog, e.g.\n * `professional`. It decides which field schema validates the anchor\n * profile, so a brain whose content or playbooks use kind-specific fields\n * must name one. Instances may override this with `kind` in brain.yaml.\n */\n kind?: string;\n\n /**\n * Default text model for this brain.\n * Can be overridden per-instance via `model` in brain.yaml.\n */\n model?: string;\n\n /** Default OpenAI reasoning effort for this brain. */\n reasoningEffort?: ReasoningEffort;\n\n /** Brain identity — character name, role, purpose, values */\n identity?: BrainIdentity;\n\n /**\n * Brain-specific agent behavior layered on top of shell-neutral tool rules.\n * Use this for model positioning such as Rover's publishing workflows or\n * Relay's team-memory/coordination focus.\n */\n agentInstructions?: string[];\n\n /**\n * Default site package — layout, routes, site plugin, and display metadata.\n * Can be overridden per-instance via `site.package` in brain.yaml.\n */\n site?: SitePackage;\n\n /**\n * Default composed theme CSS for the brain instance.\n * Can be overridden per-instance via `site.theme` in brain.yaml.\n */\n theme?: string;\n\n /**\n * Capabilities as [id, factory, config] tuples.\n * Each resolve() call invokes the factories to create fresh plugin instances.\n * Any plugin factory works — no central registry needed.\n */\n capabilities: CapabilityEntry[];\n\n /**\n * Interfaces as [id, constructor, envMapper] tuples.\n * The envMapper receives the deployment environment and returns interface config,\n * or null to skip (e.g. when credentials are missing).\n */\n interfaces: InterfaceEntry[];\n\n /**\n * Ordered capability bundles. Definition order controls deterministic\n * config, instruction, eval, and permission composition.\n */\n bundles?: CapabilityBundleDefinition[];\n\n /** Structural permission rules (no credentials) */\n permissions?: PermissionConfig;\n\n /** Deployment infrastructure config (domain, CDN, DNS) */\n deployment?: DeploymentConfigInput;\n\n /**\n * Plugin/interface IDs to disable when running in eval mode.\n * These are plugins with external side effects (chat, email, analytics, etc.)\n * that should not run during evaluation.\n */\n evalDisable?: string[];\n\n /**\n * Additional config passed directly to the app.\n * Escape hatch for anything not covered by the structured fields above.\n * Values here are merged last and can override resolved config.\n */\n extra?: Record<string, unknown>;\n}\n\n/**\n * Define a brain model.\n *\n * This is a simple identity function that provides type checking\n * for brain definitions. It returns the definition as-is.\n *\n * @example\n * ```typescript\n * import { defineBrain } from \"@brains/app\";\n * import { notePlugin } from \"@brains/note\";\n * import { MCPInterface } from \"@brains/mcp\";\n *\n * export default defineBrain({\n * name: \"my-brain\",\n * version: \"1.0.0\",\n * identity: {\n * characterName: \"Atlas\",\n * role: \"Knowledge manager\",\n * purpose: \"Organize and surface knowledge\",\n * values: [\"clarity\", \"accuracy\"],\n * },\n * capabilities: [\n * [\"note\", notePlugin, {}],\n * ],\n * interfaces: [\n * [\"mcp\", MCPInterface, (env) => ({ domain: env.DOMAIN })],\n * ],\n * });\n * ```\n */\nexport function defineBrain(definition: BrainDefinition): BrainDefinition {\n return definition;\n}\n",
|
|
8
|
-
"import { interpolateEnv } from \"@brains/utils/string-utils\";\nimport { parseYamlDocument } from \"@brains/utils/yaml\";\nimport {\n EntityActionRequiredLevelSchema,\n UserPermissionLevelSchema,\n} from \"@brains/templates\";\nimport { z } from \"@brains/utils/zod\";\nimport {\n brainAnchorConfigKindSchema,\n type BrainAnchorConfigKind,\n} from \"./brain-definition\";\nimport { reasoningEffortSchema, type ReasoningEffort } from \"./types\";\n\n/**\n * Zod schema for instance overrides parsed from brain.yaml.\n *\n * Validates the structure after YAML parsing + env interpolation.\n */\nconst pluginConfigOverrideSchema: z.ZodRecord<z.ZodString, z.ZodUnknown> =\n z.record(z.string(), z.unknown());\nconst rawRecordSchema: z.ZodRecord<z.ZodString, z.ZodUnknown> = z.record(\n z.string(),\n z.unknown(),\n);\n\nconst overrideModeSchema: z.ZodEnum<{ eval: \"eval\" }> = z.enum([\"eval\"]);\nconst overrideLogLevelSchema: z.ZodEnum<{\n debug: \"debug\";\n info: \"info\";\n warn: \"warn\";\n error: \"error\";\n}> = z.enum([\"debug\", \"info\", \"warn\", \"error\"]);\nconst overridePermissionLevelSchema = UserPermissionLevelSchema;\nconst overrideEntityActionRequiredLevelSchema = EntityActionRequiredLevelSchema;\nconst overrideEntityActionPolicyRuleSchema: z.ZodObject<{\n create: z.ZodOptional<typeof overrideEntityActionRequiredLevelSchema>;\n update: z.ZodOptional<typeof overrideEntityActionRequiredLevelSchema>;\n delete: z.ZodOptional<typeof overrideEntityActionRequiredLevelSchema>;\n extract: z.ZodOptional<typeof overrideEntityActionRequiredLevelSchema>;\n publish: z.ZodOptional<typeof overrideEntityActionRequiredLevelSchema>;\n}> = z.strictObject({\n create: overrideEntityActionRequiredLevelSchema.optional(),\n update: overrideEntityActionRequiredLevelSchema.optional(),\n delete: overrideEntityActionRequiredLevelSchema.optional(),\n extract: overrideEntityActionRequiredLevelSchema.optional(),\n publish: overrideEntityActionRequiredLevelSchema.optional(),\n});\nconst overrideEntityActionPolicyConfigSchema: z.ZodRecord<\n z.ZodString,\n typeof overrideEntityActionPolicyRuleSchema\n> = z.record(z.string(), overrideEntityActionPolicyRuleSchema);\n\nexport interface ExternalPluginDeclaration {\n [key: string]: unknown;\n package: string;\n config?: Record<string, unknown> | undefined;\n}\n\nexport const externalPluginDeclarationSchema: z.ZodObject<{\n package: z.ZodString;\n config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n}> = z.strictObject({\n /** npm package name to import from node_modules */\n package: z.string().min(1),\n /** Config object passed to the external plugin factory */\n config: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type PluginConfigOverride = Record<string, unknown>;\nexport type PluginOverrideEntry = Record<string, unknown>;\n\nexport const pluginOverrideEntrySchema: z.ZodRecord<z.ZodString, z.ZodUnknown> =\n pluginConfigOverrideSchema.superRefine((entry, ctx) => {\n if (typeof entry[\"package\"] !== \"string\") return;\n\n const parsed = externalPluginDeclarationSchema.safeParse(entry);\n if (!parsed.success) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n 'external plugin declarations may only contain \"package\" and optional nested \"config\"',\n });\n }\n });\n\nexport interface InstanceOverrides {\n brain?: string | undefined;\n anchor?: BrainAnchorConfigKind | undefined;\n site?:\n | {\n package?: string | undefined;\n variant?: string | undefined;\n theme?: string | undefined;\n themeOverride?: string | undefined;\n }\n | undefined;\n name?: string | undefined;\n kind?: string | undefined;\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\" | undefined;\n logFile?: string | undefined;\n port?: number | undefined;\n domain?: string | undefined;\n database?: string | undefined;\n model?: string | undefined;\n reasoningEffort?: ReasoningEffort | undefined;\n bundles?: string[] | undefined;\n mode?: \"eval\" | undefined;\n add?: string[] | undefined;\n remove?: string[] | undefined;\n admins?: string[] | undefined;\n anchors?: string[] | undefined;\n trusted?: string[] | undefined;\n spaces?: string[] | undefined;\n plugins?: Record<string, PluginOverrideEntry> | undefined;\n permissions?:\n | {\n admins?: string[] | undefined;\n anchors?: string[] | undefined;\n trusted?: string[] | undefined;\n rules?:\n | Array<{\n pattern: string;\n level: \"admin\" | \"trusted\" | \"public\";\n }>\n | undefined;\n entityActions?:\n | Record<\n string,\n {\n create?: \"never\" | \"admin\" | \"trusted\" | \"public\" | undefined;\n update?: \"never\" | \"admin\" | \"trusted\" | \"public\" | undefined;\n delete?: \"never\" | \"admin\" | \"trusted\" | \"public\" | undefined;\n extract?: \"never\" | \"admin\" | \"trusted\" | \"public\" | undefined;\n publish?: \"never\" | \"admin\" | \"trusted\" | \"public\" | undefined;\n }\n >\n | undefined;\n }\n | undefined;\n}\n\nconst rawInstanceOverridesSchema: z.ZodType<InstanceOverrides> = z.strictObject(\n {\n /** Brain package name (required) */\n brain: z.string().optional(),\n\n /** Anchor profile flavor. Team and organization both use collective ownership. */\n anchor: brainAnchorConfigKindSchema.optional(),\n\n /**\n * Site and theme overrides.\n *\n * - `package` names the site package to load (e.g. `@brains/site-default`).\n * Overrides any `site` set by the brain definition.\n * - `variant` is forwarded to the site plugin's config schema, so a\n * single site package can ship multiple structural flavors\n * (for example a wrapper or multi-flavor site package).\n * - `theme` selects the base theme package or inline CSS string to use\n * for styling. It is resolved separately from the site plugin.\n * - `themeOverride` appends extra CSS after the base theme. This is used\n * by the local `src/theme.css` convention so apps can layer local theme\n * overrides on top of a shared base theme without forking it.\n *\n * The whole block is optional; any subfield is optional.\n */\n site: z\n .object({\n package: z.string().optional(),\n variant: z.string().optional(),\n theme: z.string().optional(),\n themeOverride: z.string().optional(),\n })\n .optional(),\n\n /** Override instance name */\n name: z.string().optional(),\n\n /** Optional semantic profile kind selected from the composed catalog */\n kind: z.string().trim().min(1).optional(),\n\n /** Log level */\n logLevel: overrideLogLevelSchema.optional(),\n\n /** Log file path (enables usage tracking) */\n logFile: z.string().optional(),\n\n /** Production server port */\n port: z.number().optional(),\n\n /** Production domain */\n domain: z.string().optional(),\n\n /** Database URL */\n database: z.string().optional(),\n\n /** AI model — determines provider. e.g. \"gpt-4o-mini\", \"claude-haiku-4-5\", \"openai:gpt-4o\" */\n model: z.string().optional(),\n\n /** OpenAI reasoning effort. Ignored by providers that do not support it. */\n reasoningEffort: reasoningEffortSchema.optional(),\n\n /** Capability bundles selected from the canonical definition. */\n bundles: z.array(z.string().min(1)).optional(),\n\n /** Eval mode — disables plugins with side effects (defined by evalDisable in brain model) */\n mode: overrideModeSchema.optional(),\n\n /** Plugin/interface IDs to add on top of the selected bundles */\n add: z.array(z.string()).optional(),\n\n /** Plugin/interface IDs to remove from the selected bundles */\n remove: z.array(z.string()).optional(),\n\n /** Admin users (full access) */\n admins: z.array(z.string()).optional(),\n\n /** Identities that represent this personal brain's anchor in chat. */\n anchors: z.array(z.string()).optional(),\n\n /** Trusted users (elevated access) */\n trusted: z.array(z.string()).optional(),\n\n /** Shared conversation spaces for this brain/team */\n spaces: z.array(z.string()).optional(),\n\n /**\n * Per-plugin config overrides and external plugin declarations, keyed by plugin ID.\n *\n * Existing built-in override shape remains:\n * plugins.directory-sync.git.repo: ...\n *\n * External packages reserve `package` and optional nested `config`:\n * plugins.calendar.package: \"@rizom/brain-plugin-calendar\"\n * plugins.calendar.config.apiKey: \"${CALENDAR_API_KEY}\"\n */\n plugins: z.record(z.string(), pluginOverrideEntrySchema).optional(),\n\n /** Permission rules */\n permissions: z\n .object({\n admins: z.array(z.string()).optional(),\n anchors: z.array(z.string()).optional(),\n trusted: z.array(z.string()).optional(),\n rules: z\n .array(\n z.object({\n pattern: z.string(),\n level: overridePermissionLevelSchema,\n }),\n )\n .optional(),\n entityActions: overrideEntityActionPolicyConfigSchema.optional(),\n })\n .optional(),\n },\n);\n\nconst instanceOverridesSchema: z.ZodType<InstanceOverrides> =\n rawInstanceOverridesSchema;\n\n/**\n * Instance overrides — parsed from brain.yaml.\n *\n * These are deployment-specific settings that vary between instances\n * of the same brain model. Secrets stay in .env; everything else\n * goes here (with ${ENV_VAR} interpolation for referencing secrets).\n */\nexport function isExternalPluginDeclaration(\n entry: PluginOverrideEntry | undefined,\n): entry is ExternalPluginDeclaration {\n return externalPluginDeclarationSchema.safeParse(entry).success;\n}\n\n/** Return only built-in plugin config overrides, excluding external packages. */\nexport function getPluginConfigOverrides(\n plugins: InstanceOverrides[\"plugins\"] | undefined,\n): Record<string, PluginConfigOverride> {\n const result: Record<string, PluginConfigOverride> = {};\n for (const [id, entry] of Object.entries(plugins ?? {})) {\n if (!isExternalPluginDeclaration(entry)) {\n result[id] = entry;\n }\n }\n return result;\n}\n\n/** Return only external plugin package declarations. */\nexport function getExternalPluginDeclarations(\n plugins: InstanceOverrides[\"plugins\"] | undefined,\n): Record<string, ExternalPluginDeclaration> {\n const result: Record<string, ExternalPluginDeclaration> = {};\n for (const [id, entry] of Object.entries(plugins ?? {})) {\n if (isExternalPluginDeclaration(entry)) {\n result[id] = entry;\n }\n }\n return result;\n}\n\nexport const CONVENTIONAL_SITE_PACKAGE_REF = \"@brains/local-site\";\nexport const CONVENTIONAL_THEME_PACKAGE_REF = \"@brains/local-theme\";\nexport const CONVENTIONAL_SITE_CONTENT_PACKAGE_REF =\n \"@brains/local-site-content\";\n\ninterface ConventionalSiteRefs {\n sitePackageRef?: string;\n themeRef?: string;\n themeOverrideRef?: string;\n siteContentDefinitionsRef?: string;\n}\n\ntype SiteOverrides = NonNullable<InstanceOverrides[\"site\"]>;\ntype PluginOverrides = NonNullable<InstanceOverrides[\"plugins\"]>;\n\nfunction hasConventionalSiteRefs(conventions: ConventionalSiteRefs): boolean {\n return [\n conventions.sitePackageRef,\n conventions.themeRef,\n conventions.themeOverrideRef,\n conventions.siteContentDefinitionsRef,\n ].some(Boolean);\n}\n\nfunction applyConventionalSiteBlock(\n site: SiteOverrides,\n conventions: ConventionalSiteRefs,\n): SiteOverrides {\n const nextSite = { ...site };\n\n if (!nextSite.package && conventions.sitePackageRef) {\n nextSite.package = conventions.sitePackageRef;\n }\n\n if (!nextSite.theme && conventions.themeRef) {\n nextSite.theme = conventions.themeRef;\n }\n\n if (!nextSite.themeOverride && conventions.themeOverrideRef) {\n nextSite.themeOverride = conventions.themeOverrideRef;\n }\n\n return nextSite;\n}\n\nfunction applyConventionalSiteContentDefinitions(\n plugins: PluginOverrides,\n conventions: ConventionalSiteRefs,\n): PluginOverrides {\n const nextPlugins = { ...plugins };\n const siteContentConfig = { ...(nextPlugins[\"site-content\"] ?? {}) };\n\n if (\n siteContentConfig[\"definitions\"] === undefined &&\n conventions.siteContentDefinitionsRef\n ) {\n siteContentConfig[\"definitions\"] = conventions.siteContentDefinitionsRef;\n }\n\n if (Object.keys(siteContentConfig).length > 0) {\n nextPlugins[\"site-content\"] = siteContentConfig;\n }\n\n return nextPlugins;\n}\n\n/**\n * Apply convention-discovered local authoring refs only when brain.yaml does\n * not explicitly choose them.\n *\n * `themeOverrideRef` is additive: it layers local theme CSS after the base\n * theme from `site.theme` or the brain definition's default theme.\n *\n * `siteContentDefinitionsRef` wires app-local `src/site-content.ts` into the\n * `site-content` plugin config when that plugin does not already define a\n * `definitions` value explicitly.\n */\nexport function applyConventionalSiteRefs(\n overrides: InstanceOverrides,\n conventions: ConventionalSiteRefs,\n): InstanceOverrides {\n if (!hasConventionalSiteRefs(conventions)) {\n return overrides;\n }\n\n const site = applyConventionalSiteBlock(overrides.site ?? {}, conventions);\n const plugins = applyConventionalSiteContentDefinitions(\n overrides.plugins ?? {},\n conventions,\n );\n\n return {\n ...overrides,\n ...(Object.keys(site).length > 0 ? { site } : {}),\n ...(Object.keys(plugins).length > 0 ? { plugins } : {}),\n };\n}\n\n/**\n * Strip site fields consumed by the resolver before constructing the\n * site plugin config.\n *\n * - `package` is consumed by site-package resolution\n * - `theme` and `themeOverride` are consumed by theme resolution\n *\n * Remaining fields (for example `variant`) flow into the site plugin's\n * own config schema.\n */\nexport function stripSiteConfig(\n site: NonNullable<InstanceOverrides[\"site\"]> | undefined,\n): Omit<\n NonNullable<InstanceOverrides[\"site\"]>,\n \"package\" | \"theme\" | \"themeOverride\"\n> {\n const {\n package: _pkg,\n theme: _theme,\n themeOverride: _themeOverride,\n ...config\n } = site ?? {};\n return config;\n}\n\n/**\n * Error thrown when brain.yaml fails to parse or validate.\n *\n * The message is pre-formatted for direct display to the operator\n * (multi-line, includes actionable context).\n */\nexport class InstanceOverridesParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"InstanceOverridesParseError\";\n }\n}\n\n/**\n * Recursively strip `null` values from an object/array structure.\n *\n * YAML has no way to spell \"undefined\", and empty mapping values\n * (`anchors:` with nothing after the colon) parse as `null`. The\n * Zod schema uses `.optional()` which only accepts `undefined`, so\n * without this preprocessing an empty field would invalidate the\n * entire overrides object.\n *\n * Semantics: `key: null` / `key:` in YAML is treated as \"key is not\n * set\". If you want an explicit empty array or object, spell it\n * (`key: []` or `key: {}`).\n */\nfunction nullsToUndefined(value: unknown): unknown {\n if (value === null || value === undefined) return undefined;\n if (Array.isArray(value)) {\n return value.map((v) => nullsToUndefined(v)).filter((v) => v !== undefined);\n }\n const parsedRecord = rawRecordSchema.safeParse(value);\n if (parsedRecord.success) {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(parsedRecord.data)) {\n const converted = nullsToUndefined(v);\n if (converted !== undefined) {\n result[k] = converted;\n }\n }\n return result;\n }\n return value;\n}\n\ninterface ValidationIssueList {\n issues: readonly {\n path: readonly PropertyKey[];\n message: string;\n }[];\n}\n\n/**\n * Format validation issues into an operator-readable multi-line\n * message. Example:\n *\n * invalid brain.yaml:\n * - anchors: Expected array, received string\n * - plugins.mcp.port: Expected number, received string\n */\nfunction formatValidationIssues(error: ValidationIssueList): string {\n const lines = error.issues.map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n return ` - ${path}: ${issue.message}`;\n });\n return `invalid brain.yaml:\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Parse a brain.yaml string into InstanceOverrides.\n *\n * Pipeline: YAML parse → env interpolation → null-strip → Zod validate.\n *\n * Throws {@link InstanceOverridesParseError} with a pre-formatted\n * message if any step fails. Callers should catch it and either\n * surface the message to the operator or exit with a clear error.\n *\n * Previously this function silently returned `{}` on any failure,\n * which meant a typo or an empty YAML field could cause _all_\n * instance overrides to be discarded without any operator-visible\n * signal — producing a brain that booted with completely wrong\n * config. Failing loud is a deliberate choice.\n */\nexport function parseInstanceOverrides(yamlContent: string): InstanceOverrides {\n const yamlResult = parseYamlDocument(yamlContent);\n if (!yamlResult.ok) {\n throw new InstanceOverridesParseError(\n `failed to parse brain.yaml: ${yamlResult.error}`,\n );\n }\n\n const interpolated = interpolateEnv(yamlResult.data);\n const normalized = nullsToUndefined(interpolated);\n const parsed = instanceOverridesSchema.safeParse(normalized);\n\n if (!parsed.success) {\n throw new InstanceOverridesParseError(formatValidationIssues(parsed.error));\n }\n\n return parsed.data;\n}\n",
|
|
8
|
+
"import { interpolateEnv } from \"@brains/utils/string-utils\";\nimport { parseYamlDocument } from \"@brains/utils/yaml\";\nimport {\n EntityActionRequiredLevelSchema,\n UserPermissionLevelSchema,\n} from \"@brains/templates\";\nimport { z } from \"@brains/utils/zod\";\nimport {\n brainAnchorConfigKindSchema,\n type BrainAnchorConfigKind,\n} from \"./brain-definition\";\nimport { reasoningEffortSchema, type ReasoningEffort } from \"./types\";\n\n/**\n * Zod schema for instance overrides parsed from brain.yaml.\n *\n * Validates the structure after YAML parsing + env interpolation.\n */\nconst pluginConfigOverrideSchema: z.ZodRecord<z.ZodString, z.ZodUnknown> =\n z.record(z.string(), z.unknown());\nconst rawRecordSchema: z.ZodRecord<z.ZodString, z.ZodUnknown> = z.record(\n z.string(),\n z.unknown(),\n);\n\nconst overrideModeSchema: z.ZodEnum<{ eval: \"eval\" }> = z.enum([\"eval\"]);\nconst overrideLogLevelSchema: z.ZodEnum<{\n debug: \"debug\";\n info: \"info\";\n warn: \"warn\";\n error: \"error\";\n}> = z.enum([\"debug\", \"info\", \"warn\", \"error\"]);\nconst overridePermissionLevelSchema = UserPermissionLevelSchema;\nconst overrideEntityActionRequiredLevelSchema = EntityActionRequiredLevelSchema;\nconst overrideEntityActionPolicyRuleSchema: z.ZodObject<{\n create: z.ZodOptional<typeof overrideEntityActionRequiredLevelSchema>;\n update: z.ZodOptional<typeof overrideEntityActionRequiredLevelSchema>;\n delete: z.ZodOptional<typeof overrideEntityActionRequiredLevelSchema>;\n extract: z.ZodOptional<typeof overrideEntityActionRequiredLevelSchema>;\n publish: z.ZodOptional<typeof overrideEntityActionRequiredLevelSchema>;\n}> = z.strictObject({\n create: overrideEntityActionRequiredLevelSchema.optional(),\n update: overrideEntityActionRequiredLevelSchema.optional(),\n delete: overrideEntityActionRequiredLevelSchema.optional(),\n extract: overrideEntityActionRequiredLevelSchema.optional(),\n publish: overrideEntityActionRequiredLevelSchema.optional(),\n});\nconst overrideEntityActionPolicyConfigSchema: z.ZodRecord<\n z.ZodString,\n typeof overrideEntityActionPolicyRuleSchema\n> = z.record(z.string(), overrideEntityActionPolicyRuleSchema);\n\nexport interface ExternalPluginDeclaration {\n [key: string]: unknown;\n package: string;\n config?: Record<string, unknown> | undefined;\n}\n\nexport const externalPluginDeclarationSchema: z.ZodObject<{\n package: z.ZodString;\n config: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;\n}> = z.strictObject({\n /** npm package name to import from node_modules */\n package: z.string().min(1),\n /** Config object passed to the external plugin factory */\n config: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type PluginConfigOverride = Record<string, unknown>;\nexport type PluginOverrideEntry = Record<string, unknown>;\n\nexport const pluginOverrideEntrySchema: z.ZodRecord<z.ZodString, z.ZodUnknown> =\n pluginConfigOverrideSchema.superRefine((entry, ctx) => {\n if (typeof entry[\"package\"] !== \"string\") return;\n\n const parsed = externalPluginDeclarationSchema.safeParse(entry);\n if (!parsed.success) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n 'external plugin declarations may only contain \"package\" and optional nested \"config\"',\n });\n }\n });\n\nexport interface InstanceOverrides {\n brain?: string | undefined;\n anchor?: BrainAnchorConfigKind | undefined;\n site?:\n | {\n package?: string | undefined;\n variant?: string | undefined;\n theme?: string | undefined;\n themeOverride?: string | undefined;\n }\n | undefined;\n name?: string | undefined;\n kind?: string | undefined;\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\" | undefined;\n logFile?: string | undefined;\n port?: number | undefined;\n domain?: string | undefined;\n database?: string | undefined;\n model?: string | undefined;\n reasoningEffort?: ReasoningEffort | undefined;\n bundles?: string[] | undefined;\n mode?: \"eval\" | undefined;\n add?: string[] | undefined;\n remove?: string[] | undefined;\n admins?: string[] | undefined;\n anchors?: string[] | undefined;\n trusted?: string[] | undefined;\n spaces?: string[] | undefined;\n plugins?: Record<string, PluginOverrideEntry> | undefined;\n permissions?:\n | {\n admins?: string[] | undefined;\n anchors?: string[] | undefined;\n trusted?: string[] | undefined;\n rules?:\n | Array<{\n pattern: string;\n level: \"admin\" | \"trusted\" | \"public\";\n }>\n | undefined;\n entityActions?:\n | Record<\n string,\n {\n create?: \"never\" | \"admin\" | \"trusted\" | \"public\" | undefined;\n update?: \"never\" | \"admin\" | \"trusted\" | \"public\" | undefined;\n delete?: \"never\" | \"admin\" | \"trusted\" | \"public\" | undefined;\n extract?: \"never\" | \"admin\" | \"trusted\" | \"public\" | undefined;\n publish?: \"never\" | \"admin\" | \"trusted\" | \"public\" | undefined;\n }\n >\n | undefined;\n }\n | undefined;\n}\n\nconst rawInstanceOverridesSchema: z.ZodType<InstanceOverrides> = z.strictObject(\n {\n /** Brain package name (required) */\n brain: z.string().optional(),\n\n /** Anchor profile flavor. Team and organization both use collective ownership. */\n anchor: brainAnchorConfigKindSchema.optional(),\n\n /**\n * Site and theme overrides.\n *\n * - `package` names the site package to load (e.g. `@brains/site-default`).\n * Overrides any `site` set by the brain definition.\n * - `variant` is forwarded to the site plugin's config schema, so a\n * single site package can ship multiple structural flavors\n * (for example a wrapper or multi-flavor site package).\n * - `theme` selects the base theme package or inline CSS string to use\n * for styling. It is resolved separately from the site plugin.\n * - `themeOverride` appends extra CSS after the base theme. This is used\n * by the local `src/theme.css` convention so apps can layer local theme\n * overrides on top of a shared base theme without forking it.\n *\n * The whole block is optional; any subfield is optional.\n */\n site: z\n .object({\n package: z.string().optional(),\n variant: z.string().optional(),\n theme: z.string().optional(),\n themeOverride: z.string().optional(),\n })\n .optional(),\n\n /** Override instance name */\n name: z.string().optional(),\n\n /** Optional semantic profile kind selected from the composed catalog */\n kind: z.string().trim().min(1).optional(),\n\n /** Log level */\n logLevel: overrideLogLevelSchema.optional(),\n\n /** Log file path (enables usage tracking) */\n logFile: z.string().optional(),\n\n /** Production server port */\n port: z.number().optional(),\n\n /** Production domain */\n domain: z.string().optional(),\n\n /** Database URL */\n database: z.string().optional(),\n\n /** AI model — determines provider. e.g. \"gpt-4o-mini\", \"claude-haiku-4-5\", \"openai:gpt-4o\" */\n model: z.string().optional(),\n\n /** OpenAI reasoning effort. Ignored by providers that do not support it. */\n reasoningEffort: reasoningEffortSchema.optional(),\n\n /** Capability bundles selected from the canonical definition. */\n bundles: z.array(z.string().min(1)).optional(),\n\n /** Eval mode — disables plugins with side effects (defined by evalDisable in brain model) */\n mode: overrideModeSchema.optional(),\n\n /** Plugin/interface IDs to add on top of the selected bundles */\n add: z.array(z.string()).optional(),\n\n /** Plugin/interface IDs to remove from the selected bundles */\n remove: z.array(z.string()).optional(),\n\n /** Admin users (full access) */\n admins: z.array(z.string()).optional(),\n\n /** Identities that represent this personal brain's anchor in chat. */\n anchors: z.array(z.string()).optional(),\n\n /** Trusted users (elevated access) */\n trusted: z.array(z.string()).optional(),\n\n /** Shared conversation spaces for this brain/team */\n spaces: z.array(z.string()).optional(),\n\n /**\n * Per-plugin config overrides and external plugin declarations, keyed by plugin ID.\n *\n * Existing built-in override shape remains:\n * plugins.directory-sync.git.repo: ...\n *\n * External packages reserve `package` and optional nested `config`:\n * plugins.calendar.package: \"@rizom/brain-plugin-calendar\"\n * plugins.calendar.config.apiKey: \"${CALENDAR_API_KEY}\"\n */\n plugins: z.record(z.string(), pluginOverrideEntrySchema).optional(),\n\n /** Permission rules */\n permissions: z\n .object({\n admins: z.array(z.string()).optional(),\n anchors: z.array(z.string()).optional(),\n trusted: z.array(z.string()).optional(),\n rules: z\n .array(\n z.object({\n pattern: z.string(),\n level: overridePermissionLevelSchema,\n }),\n )\n .optional(),\n entityActions: overrideEntityActionPolicyConfigSchema.optional(),\n })\n .optional(),\n },\n);\n\nconst instanceOverridesSchema: z.ZodType<InstanceOverrides> =\n rawInstanceOverridesSchema;\n\n/**\n * Instance overrides — parsed from brain.yaml.\n *\n * These are deployment-specific settings that vary between instances\n * of the same brain model. Secrets stay in .env; everything else\n * goes here (with ${ENV_VAR} interpolation for referencing secrets).\n */\nexport function isExternalPluginDeclaration(\n entry: PluginOverrideEntry | undefined,\n): entry is ExternalPluginDeclaration {\n return externalPluginDeclarationSchema.safeParse(entry).success;\n}\n\n/** Return only built-in plugin config overrides, excluding external packages. */\nexport function getPluginConfigOverrides(\n plugins: InstanceOverrides[\"plugins\"] | undefined,\n): Record<string, PluginConfigOverride> {\n const result: Record<string, PluginConfigOverride> = {};\n for (const [id, entry] of Object.entries(plugins ?? {})) {\n if (!isExternalPluginDeclaration(entry)) {\n result[id] = entry;\n }\n }\n return result;\n}\n\n/** Return only external plugin package declarations. */\nexport function getExternalPluginDeclarations(\n plugins: InstanceOverrides[\"plugins\"] | undefined,\n): Record<string, ExternalPluginDeclaration> {\n const result: Record<string, ExternalPluginDeclaration> = {};\n for (const [id, entry] of Object.entries(plugins ?? {})) {\n if (isExternalPluginDeclaration(entry)) {\n result[id] = entry;\n }\n }\n return result;\n}\n\nexport const CONVENTIONAL_SITE_PACKAGE_REF = \"@brains/local-site\";\nexport const CONVENTIONAL_THEME_PACKAGE_REF = \"@brains/local-theme\";\nexport const CONVENTIONAL_SITE_CONTENT_PACKAGE_REF =\n \"@brains/local-site-content\";\n\ninterface ConventionalSiteRefs {\n sitePackageRef?: string;\n themeRef?: string;\n themeOverrideRef?: string;\n siteContentDefinitionsRef?: string;\n}\n\ntype SiteOverrides = NonNullable<InstanceOverrides[\"site\"]>;\ntype PluginOverrides = NonNullable<InstanceOverrides[\"plugins\"]>;\n\nfunction hasConventionalSiteRefs(conventions: ConventionalSiteRefs): boolean {\n return [\n conventions.sitePackageRef,\n conventions.themeRef,\n conventions.themeOverrideRef,\n conventions.siteContentDefinitionsRef,\n ].some(Boolean);\n}\n\nfunction applyConventionalSiteBlock(\n site: SiteOverrides,\n conventions: ConventionalSiteRefs,\n): SiteOverrides {\n const nextSite = { ...site };\n\n if (conventions.sitePackageRef) {\n nextSite.package = conventions.sitePackageRef;\n }\n\n if (!nextSite.theme && conventions.themeRef) {\n nextSite.theme = conventions.themeRef;\n }\n\n if (!nextSite.themeOverride && conventions.themeOverrideRef) {\n nextSite.themeOverride = conventions.themeOverrideRef;\n }\n\n return nextSite;\n}\n\nfunction applyConventionalSiteContentDefinitions(\n plugins: PluginOverrides,\n conventions: ConventionalSiteRefs,\n): PluginOverrides {\n const nextPlugins = { ...plugins };\n const siteContentConfig = { ...(nextPlugins[\"site-content\"] ?? {}) };\n\n if (\n siteContentConfig[\"definitions\"] === undefined &&\n conventions.siteContentDefinitionsRef\n ) {\n siteContentConfig[\"definitions\"] = conventions.siteContentDefinitionsRef;\n }\n\n if (Object.keys(siteContentConfig).length > 0) {\n nextPlugins[\"site-content\"] = siteContentConfig;\n }\n\n return nextPlugins;\n}\n\n/**\n * Apply convention-discovered local authoring refs.\n *\n * `sitePackageRef` selects the already-composed local site package. When\n * brain.yaml names a base package, registration composes `src/site.ts` over it\n * before this helper replaces the effective package ref.\n *\n * `themeOverrideRef` is additive: it layers local theme CSS after the base\n * theme from `site.theme` or the brain definition's default theme.\n *\n * `siteContentDefinitionsRef` wires app-local `src/site-content.ts` into the\n * `site-content` plugin config when that plugin does not already define a\n * `definitions` value explicitly.\n */\nexport function applyConventionalSiteRefs(\n overrides: InstanceOverrides,\n conventions: ConventionalSiteRefs,\n): InstanceOverrides {\n if (!hasConventionalSiteRefs(conventions)) {\n return overrides;\n }\n\n const site = applyConventionalSiteBlock(overrides.site ?? {}, conventions);\n const plugins = applyConventionalSiteContentDefinitions(\n overrides.plugins ?? {},\n conventions,\n );\n\n return {\n ...overrides,\n ...(Object.keys(site).length > 0 ? { site } : {}),\n ...(Object.keys(plugins).length > 0 ? { plugins } : {}),\n };\n}\n\n/**\n * Strip site fields consumed by the resolver before constructing the\n * site plugin config.\n *\n * - `package` is consumed by site-package resolution\n * - `theme` and `themeOverride` are consumed by theme resolution\n *\n * Remaining fields (for example `variant`) flow into the site plugin's\n * own config schema.\n */\nexport function stripSiteConfig(\n site: NonNullable<InstanceOverrides[\"site\"]> | undefined,\n): Omit<\n NonNullable<InstanceOverrides[\"site\"]>,\n \"package\" | \"theme\" | \"themeOverride\"\n> {\n const {\n package: _pkg,\n theme: _theme,\n themeOverride: _themeOverride,\n ...config\n } = site ?? {};\n return config;\n}\n\n/**\n * Error thrown when brain.yaml fails to parse or validate.\n *\n * The message is pre-formatted for direct display to the operator\n * (multi-line, includes actionable context).\n */\nexport class InstanceOverridesParseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"InstanceOverridesParseError\";\n }\n}\n\n/**\n * Recursively strip `null` values from an object/array structure.\n *\n * YAML has no way to spell \"undefined\", and empty mapping values\n * (`anchors:` with nothing after the colon) parse as `null`. The\n * Zod schema uses `.optional()` which only accepts `undefined`, so\n * without this preprocessing an empty field would invalidate the\n * entire overrides object.\n *\n * Semantics: `key: null` / `key:` in YAML is treated as \"key is not\n * set\". If you want an explicit empty array or object, spell it\n * (`key: []` or `key: {}`).\n */\nfunction nullsToUndefined(value: unknown): unknown {\n if (value === null || value === undefined) return undefined;\n if (Array.isArray(value)) {\n return value.map((v) => nullsToUndefined(v)).filter((v) => v !== undefined);\n }\n const parsedRecord = rawRecordSchema.safeParse(value);\n if (parsedRecord.success) {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(parsedRecord.data)) {\n const converted = nullsToUndefined(v);\n if (converted !== undefined) {\n result[k] = converted;\n }\n }\n return result;\n }\n return value;\n}\n\ninterface ValidationIssueList {\n issues: readonly {\n path: readonly PropertyKey[];\n message: string;\n }[];\n}\n\n/**\n * Format validation issues into an operator-readable multi-line\n * message. Example:\n *\n * invalid brain.yaml:\n * - anchors: Expected array, received string\n * - plugins.mcp.port: Expected number, received string\n */\nfunction formatValidationIssues(error: ValidationIssueList): string {\n const lines = error.issues.map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join(\".\") : \"(root)\";\n return ` - ${path}: ${issue.message}`;\n });\n return `invalid brain.yaml:\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Parse a brain.yaml string into InstanceOverrides.\n *\n * Pipeline: YAML parse → env interpolation → null-strip → Zod validate.\n *\n * Throws {@link InstanceOverridesParseError} with a pre-formatted\n * message if any step fails. Callers should catch it and either\n * surface the message to the operator or exit with a clear error.\n *\n * Previously this function silently returned `{}` on any failure,\n * which meant a typo or an empty YAML field could cause _all_\n * instance overrides to be discarded without any operator-visible\n * signal — producing a brain that booted with completely wrong\n * config. Failing loud is a deliberate choice.\n */\nexport function parseInstanceOverrides(yamlContent: string): InstanceOverrides {\n const yamlResult = parseYamlDocument(yamlContent);\n if (!yamlResult.ok) {\n throw new InstanceOverridesParseError(\n `failed to parse brain.yaml: ${yamlResult.error}`,\n );\n }\n\n const interpolated = interpolateEnv(yamlResult.data);\n const normalized = nullsToUndefined(interpolated);\n const parsed = instanceOverridesSchema.safeParse(normalized);\n\n if (!parsed.success) {\n throw new InstanceOverridesParseError(formatValidationIssues(parsed.error));\n }\n\n return parsed.data;\n}\n",
|
|
9
9
|
"import { z } from \"@brains/utils/zod\";\n\nconst recordSchema = z.record(z.string(), z.unknown());\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return recordSchema.safeParse(value).success;\n}\n\n/**\n * Merge a brain.yaml override over a brain-model default.\n *\n * A `null` in the override deletes the key rather than setting it to null,\n * which is how an instance turns off something its model switched on.\n */\nexport function deepMerge(\n base: Record<string, unknown>,\n override: Record<string, unknown>,\n): Record<string, unknown> {\n const result = { ...base };\n for (const key of Object.keys(override)) {\n const overrideVal = override[key];\n if (overrideVal === null) {\n delete result[key];\n } else if (isPlainObject(result[key]) && isPlainObject(overrideVal)) {\n result[key] = deepMerge(result[key], overrideVal);\n } else {\n result[key] = overrideVal;\n }\n }\n return result;\n}\n",
|
|
10
10
|
"import { z } from \"@brains/utils/zod\";\nimport type { PluginFactory } from \"../brain-definition\";\nimport type { ExternalPluginDeclaration } from \"../instance-overrides\";\nimport { getPackage, hasPackage } from \"../package-registry\";\n\nconst pluginFactorySchema = z.custom<PluginFactory>(\n (value) => typeof value === \"function\",\n);\nconst externalPluginPackageSchema = z.looseObject({\n plugin: pluginFactorySchema.optional(),\n});\n\n/** Matches scoped npm package names like @rizom/theme-default (no colons, no dots) */\nconst SCOPED_PACKAGE_PATTERN = /^@[\\w-]+\\/[\\w-]+$/;\n\n/**\n * Check if a string looks like a scoped npm package reference.\n * Excludes Matrix userIds (@user:server), email addresses, CSS selectors, etc.\n */\nexport function isScopedPackageRef(value: string): boolean {\n return SCOPED_PACKAGE_PATTERN.test(value);\n}\n\n/**\n * Resolve scoped package references in a config object.\n * Looks up values in the package registry (populated before resolve() is called).\n */\nfunction isRegisteredScopedPackageRef(value: unknown): value is string {\n return (\n typeof value === \"string\" && isScopedPackageRef(value) && hasPackage(value)\n );\n}\n\nfunction resolvePackageRefValue(value: unknown): unknown {\n return isRegisteredScopedPackageRef(value) ? getPackage(value) : value;\n}\n\nfunction resolvePackageRefs(\n config: Record<string, unknown>,\n): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(config).map(([key, value]) => [\n key,\n resolvePackageRefValue(value),\n ]),\n );\n}\n\n/**\n * Resolve package references across all plugin override configs.\n */\nexport function resolveAllPackageRefs(\n pluginOverrides: Record<string, Record<string, unknown>>,\n): Record<string, Record<string, unknown>> {\n return Object.fromEntries(\n Object.entries(pluginOverrides).map(([pluginId, config]) => [\n pluginId,\n resolvePackageRefs(config),\n ]),\n );\n}\n\nfunction getRegisteredExternalPluginPackage(\n pluginId: string,\n packageName: string,\n): unknown {\n if (!hasPackage(packageName)) {\n throw new Error(\n `External plugin package \"${packageName}\" for plugins.${pluginId} is not registered. Install it and ensure it is imported before resolve().`,\n );\n }\n\n return getPackage(packageName);\n}\n\n// External plugin packages may export the factory as either the default export\n// or a named `plugin` export — the public authoring contract documented in\n// docs/external-plugin-authoring.md accepts both.\nfunction pluginFactoryFromPackage(pkg: unknown): PluginFactory | undefined {\n const directFactory = pluginFactorySchema.safeParse(pkg);\n if (directFactory.success) return directFactory.data;\n\n const packageShape = externalPluginPackageSchema.safeParse(pkg);\n return packageShape.success ? packageShape.data.plugin : undefined;\n}\n\nexport function resolveExternalPluginFactory(\n pluginId: string,\n declaration: ExternalPluginDeclaration,\n): PluginFactory {\n const packageName = declaration.package;\n const pkg = getRegisteredExternalPluginPackage(pluginId, packageName);\n const factory = pluginFactoryFromPackage(pkg);\n\n if (factory) {\n return factory;\n }\n\n throw new Error(\n `External plugin package \"${packageName}\" for plugins.${pluginId} must export a plugin factory as the package default or as a named \"plugin\" export.`,\n );\n}\n",
|
|
11
11
|
"import {\n EntityActionRequiredLevelSchema,\n UserPermissionLevelSchema,\n entityActionPolicyConfigSchema,\n type EntityActionPolicyConfigInput,\n type PermissionConfig,\n type UserPermissionLevel,\n} from \"@brains/templates\";\nimport { z } from \"@brains/utils/zod\";\nimport type { CapabilityBundleDefinition } from \"./bundle-definition\";\nimport type { ResolvedBundlePermissionContribution } from \"./bundle-resolution\";\n\nconst permissionRuleSchema = z.strictObject({\n pattern: z.string(),\n level: UserPermissionLevelSchema,\n});\n\nconst bundlePermissionConfigSchema = z.strictObject({\n admins: z.array(z.string()).optional(),\n anchors: z.array(z.string()).optional(),\n trusted: z.array(z.string()).optional(),\n rules: z.array(permissionRuleSchema).optional(),\n entityActions: entityActionPolicyConfigSchema.optional(),\n});\n\ninterface SourcedValue<T> {\n value: T;\n sources: Set<string>;\n}\n\ninterface PermissionState {\n admins: Set<string>;\n anchors: Set<string>;\n trusted: Set<string>;\n rules: Map<string, SourcedValue<UserPermissionLevel>>;\n entityActions: Map<string, SourcedValue<string>>;\n}\n\nfunction createPermissionState(): PermissionState {\n return {\n admins: new Set(),\n anchors: new Set(),\n trusted: new Set(),\n rules: new Map(),\n entityActions: new Map(),\n };\n}\n\nfunction assignSourcedValue<T>(input: {\n values: Map<string, SourcedValue<T>>;\n key: string;\n displayPath: string;\n value: T;\n bundleId: string;\n overrides: string | undefined;\n}): boolean {\n const { values, key, displayPath, value, bundleId, overrides } = input;\n const existing = values.get(key);\n if (!existing) {\n values.set(key, { value, sources: new Set([bundleId]) });\n return false;\n }\n\n if (Object.is(existing.value, value)) {\n existing.sources.add(bundleId);\n return false;\n }\n\n const canOverride =\n overrides !== undefined &&\n existing.sources.size > 0 &&\n [...existing.sources].every((source) => source === overrides);\n if (!canOverride) {\n const existingSources = [...existing.sources]\n .map((source) => `\"${source}\"`)\n .join(\", \");\n throw new Error(\n `Permission conflict at \"${displayPath}\" between bundles ${existingSources} and \"${bundleId}\"`,\n );\n }\n\n values.set(key, { value, sources: new Set([bundleId]) });\n return true;\n}\n\nfunction parseContribution(\n contribution: ResolvedBundlePermissionContribution,\n): PermissionConfig {\n const parsed = bundlePermissionConfigSchema.safeParse(contribution.config);\n if (!parsed.success) {\n throw new Error(\n `Invalid permission contribution from bundle \"${contribution.bundleId}\" for member \"${contribution.member}\": ${parsed.error.message}`,\n );\n }\n return {\n ...(parsed.data.admins ? { admins: parsed.data.admins } : {}),\n ...(parsed.data.anchors ? { anchors: parsed.data.anchors } : {}),\n ...(parsed.data.trusted ? { trusted: parsed.data.trusted } : {}),\n ...(parsed.data.rules ? { rules: parsed.data.rules } : {}),\n ...(parsed.data.entityActions\n ? { entityActions: parsed.data.entityActions }\n : {}),\n };\n}\n\nfunction composePermissionContributions(\n contributions: readonly ResolvedBundlePermissionContribution[],\n requireUsedOverrides: boolean,\n): PermissionConfig | undefined {\n if (contributions.length === 0) return undefined;\n\n const state = createPermissionState();\n for (const contribution of contributions) {\n const config = parseContribution(contribution);\n let usedOverride = false;\n\n for (const admin of config.admins ?? []) state.admins.add(admin);\n for (const anchor of config.anchors ?? []) state.anchors.add(anchor);\n for (const trusted of config.trusted ?? []) state.trusted.add(trusted);\n\n for (const rule of config.rules ?? []) {\n const didOverride = assignSourcedValue({\n values: state.rules,\n key: rule.pattern,\n displayPath: `rules.${rule.pattern}`,\n value: rule.level,\n bundleId: contribution.bundleId,\n overrides: contribution.overrides,\n });\n usedOverride ||= didOverride;\n }\n\n for (const [entityType, policy] of Object.entries(\n config.entityActions ?? {},\n )) {\n for (const [action, requiredLevel] of Object.entries(policy)) {\n if (requiredLevel === undefined) continue;\n const key = `${entityType}\\u0000${action}`;\n const didOverride = assignSourcedValue({\n values: state.entityActions,\n key,\n displayPath: `entityActions.${entityType}.${action}`,\n value: EntityActionRequiredLevelSchema.parse(requiredLevel),\n bundleId: contribution.bundleId,\n overrides: contribution.overrides,\n });\n usedOverride ||= didOverride;\n }\n }\n\n if (requireUsedOverrides && contribution.overrides && !usedOverride) {\n throw new Error(\n `Permission override of \"${contribution.overrides}\" in bundle \"${contribution.bundleId}\" does not replace a conflicting permission`,\n );\n }\n }\n\n const entityActions: EntityActionPolicyConfigInput = {};\n for (const [key, sourced] of state.entityActions) {\n const separator = key.indexOf(\"\\u0000\");\n const entityType = key.slice(0, separator);\n const action = key.slice(separator + 1);\n entityActions[entityType] = {\n ...(entityActions[entityType] ?? {}),\n [action]: sourced.value,\n };\n }\n\n return {\n ...(state.admins.size > 0 ? { admins: [...state.admins] } : {}),\n ...(state.anchors.size > 0 ? { anchors: [...state.anchors] } : {}),\n ...(state.trusted.size > 0 ? { trusted: [...state.trusted] } : {}),\n ...(state.rules.size > 0\n ? {\n rules: [...state.rules].map(([pattern, sourced]) => ({\n pattern,\n level: sourced.value,\n })),\n }\n : {}),\n ...(Object.keys(entityActions).length > 0 ? { entityActions } : {}),\n };\n}\n\nfunction allPermissionContributions(\n definitions: readonly CapabilityBundleDefinition[],\n): ResolvedBundlePermissionContribution[] {\n return definitions.flatMap((definition) =>\n (definition.permissions ?? []).map(({ member, config, overrides }) => ({\n bundleId: definition.id,\n member,\n config,\n ...(overrides ? { overrides } : {}),\n })),\n );\n}\n\n/** Validate all definitions, then compose only active member contributions. */\nexport function resolveBundlePermissionConfig(\n definitions: readonly CapabilityBundleDefinition[],\n activeContributions: readonly ResolvedBundlePermissionContribution[],\n): PermissionConfig | undefined {\n composePermissionContributions(allPermissionContributions(definitions), true);\n return composePermissionContributions(activeContributions, false);\n}\n",
|
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
"import {\n SYSTEM_CHANNELS,\n type IShell,\n type Plugin,\n type PluginCapabilities,\n} from \"@brains/plugins\";\nimport { SITE_BUILDER_CHANNELS } from \"@brains/contracts\";\nimport { withThemeBase } from \"@brains/theme-base\";\nimport { z } from \"@brains/utils/zod\";\nimport type { BrainDefinition } from \"../brain-definition\";\nimport {\n CONVENTIONAL_SITE_PACKAGE_REF,\n stripSiteConfig,\n type InstanceOverrides,\n} from \"../instance-overrides\";\nimport {\n createSiteContentTemplates,\n extendSite,\n sectionGroupToTemplates,\n sitePackageSchema,\n themeCssSchema,\n type ConventionalSiteOverrides,\n type SiteContentDefinition,\n type SitePackage,\n type SiteSectionGroup,\n} from \"../site-package\";\nimport { getPackage, hasPackage } from \"../package-registry\";\nimport { isActive, type ActiveIds } from \"./active-ids\";\n\nexport function normalizeSiteContent(\n content: SitePackage[\"content\"],\n): SiteContentDefinition[] {\n if (!content) return [];\n return Array.isArray(content) ? content : [content];\n}\n\nfunction normalizeSiteSections(\n sections: SitePackage[\"sections\"],\n): SiteSectionGroup[] {\n if (!sections) return [];\n return Array.isArray(sections) ? sections : [sections];\n}\n\nclass DeclarativeSitePlugin implements Plugin {\n readonly id = \"site-package\";\n readonly version = \"0.1.0\";\n readonly type = \"service\" as const;\n readonly description = \"Declarative site package adapter\";\n\n readonly packageName: string;\n private readonly site: SitePackage;\n\n constructor(packageName: string, site: SitePackage) {\n this.packageName = packageName;\n this.site = site;\n }\n\n async register(shell: IShell): Promise<PluginCapabilities> {\n for (const definition of normalizeSiteContent(this.site.content)) {\n shell.registerTemplates(\n createSiteContentTemplates(definition),\n definition.namespace,\n );\n }\n\n for (const group of normalizeSiteSections(this.site.sections)) {\n shell.registerTemplates(sectionGroupToTemplates(group), group.namespace);\n }\n\n if (this.site.headScripts?.length) {\n const messaging = shell.getMessageBus();\n messaging.subscribe(SYSTEM_CHANNELS.pluginsRegistered, async () => {\n for (const [index, script] of this.site.headScripts?.entries() ?? []) {\n await messaging.send({\n type: SITE_BUILDER_CHANNELS.headScriptRegister,\n sender: this.id,\n payload: {\n pluginId: `${this.id}:${index}`,\n script,\n },\n });\n }\n return { success: true };\n });\n }\n\n return { tools: [], resources: [] };\n }\n}\n\nexport function instantiateSitePlugins(\n site: SitePackage | undefined,\n overrides: Omit<InstanceOverrides, \"brain\"> | undefined,\n activeIds: ActiveIds,\n allowImplicitSite = false,\n): Plugin[] {\n if (!site || (!allowImplicitSite && !isActive(activeIds, \"site-builder\"))) {\n return [];\n }\n\n const plugins: Plugin[] = [];\n if (site.plugin) {\n plugins.push(\n site.plugin({\n entityDisplay: site.entityDisplay,\n ...stripSiteConfig(overrides?.site),\n }),\n );\n }\n\n if (site.content || site.headScripts?.length) {\n plugins.push(\n new DeclarativeSitePlugin(\n overrides?.site?.package ?? \"@rizom/site-package\",\n site,\n ),\n );\n }\n\n return plugins;\n}\n\n/**\n * Resolve the site package from brain.yaml override or brain definition default.\n * brain.yaml `site.package` (a @-prefixed package ref) takes priority.\n */\nconst routeDefinitionOverrideSchema = z.looseObject({\n id: z.string().min(1),\n});\n\nconst entityDisplayEntryOverrideSchema = z.looseObject({\n label: z.string().min(1),\n});\n\nconst sitePackagePluginOverrideSchema = z.custom<(...args: never[]) => unknown>(\n (value) => typeof value === \"function\",\n);\n\nconst sitePackageOverridesShapeSchema = z.looseObject({\n layouts: z.record(z.string(), z.unknown()).optional(),\n plugin: sitePackagePluginOverrideSchema.optional(),\n pluginConfig: z.record(z.string(), z.unknown()).optional(),\n routes: z.array(routeDefinitionOverrideSchema).optional(),\n entityDisplay: z\n .record(z.string(), entityDisplayEntryOverrideSchema)\n .optional(),\n content: z.unknown().optional(),\n themeOverride: z.string().optional(),\n headScripts: z.array(z.string()).optional(),\n staticAssets: z.record(z.string(), z.string()).optional(),\n});\n\n// Validate the shape loosely (plugin as a bare function, layouts/routes as\n// records) but declare the trusted output type once here at the parse\n// boundary — same idiom as sitePackageSchema in site-package.ts.\nconst conventionalSiteOverridesSchema = z.custom<ConventionalSiteOverrides>(\n (value) => sitePackageOverridesShapeSchema.safeParse(value).success,\n);\n\nfunction applySitePluginConfig(\n site: SitePackage,\n pluginConfig: Record<string, unknown> | undefined,\n): SitePackage {\n if (!pluginConfig || !site.plugin) return site;\n\n const plugin = site.plugin;\n return {\n ...site,\n plugin: (config?: Record<string, unknown>) =>\n plugin({\n ...pluginConfig,\n ...(config ?? {}),\n }),\n };\n}\n\nfunction resolveConventionalSitePackage(\n pkg: unknown,\n definition: BrainDefinition,\n): SitePackage | undefined {\n if (!definition.site) return undefined;\n\n const parsedOverrides = conventionalSiteOverridesSchema.safeParse(pkg);\n if (!parsedOverrides.success) return undefined;\n\n const { pluginConfig, ...siteOverrides } = parsedOverrides.data;\n const siteWithStructure = extendSite(definition.site, siteOverrides);\n\n return applySitePluginConfig(siteWithStructure, pluginConfig);\n}\n\nfunction resolveRegisteredSitePackage(\n pkgRef: string,\n pkg: unknown,\n definition: BrainDefinition,\n): SitePackage | undefined {\n if (pkgRef === CONVENTIONAL_SITE_PACKAGE_REF) {\n const conventionalSite = resolveConventionalSitePackage(pkg, definition);\n if (conventionalSite) return conventionalSite;\n }\n\n const parsedSitePackage = sitePackageSchema.safeParse(pkg);\n return parsedSitePackage.success ? parsedSitePackage.data : undefined;\n}\n\nexport function resolveSitePackage(\n definition: BrainDefinition,\n overrides?: Omit<InstanceOverrides, \"brain\">,\n): SitePackage | undefined {\n const pkgRef = overrides?.site?.package;\n if (!pkgRef) {\n return definition.site;\n }\n\n if (!hasPackage(pkgRef)) {\n throw new Error(\n `brain.yaml site.package \"${pkgRef}\" could not be resolved — the package is not installed or failed to import. Refusing to fall back to the default site.`,\n );\n }\n\n const sitePackage = resolveRegisteredSitePackage(\n pkgRef,\n getPackage(pkgRef),\n definition,\n );\n if (sitePackage) {\n return sitePackage;\n }\n\n throw new Error(`Package \"${pkgRef}\" is not a valid SitePackage`);\n}\n\nfunction resolveThemeCssRef(refOrCss: string): string {\n if (hasPackage(refOrCss)) {\n const pkg = getPackage(refOrCss);\n const parsed = themeCssSchema.safeParse(pkg);\n if (!parsed.success) {\n throw new Error(`Package \"${refOrCss}\" does not export theme CSS`);\n }\n return parsed.data;\n }\n\n return refOrCss;\n}\n\nexport function resolveTheme(\n definition: BrainDefinition,\n overrides?: Omit<InstanceOverrides, \"brain\">,\n site?: SitePackage,\n): string | undefined {\n const baseTheme = overrides?.site?.theme\n ? resolveThemeCssRef(overrides.site.theme)\n : definition.theme;\n const siteThemeOverride = site?.themeOverride;\n const instanceThemeOverride = overrides?.site?.themeOverride\n ? resolveThemeCssRef(overrides.site.themeOverride)\n : undefined;\n const theme = [baseTheme, siteThemeOverride, instanceThemeOverride]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n if (!theme) {\n return undefined;\n }\n\n return withThemeBase(theme);\n}\n"
|
|
14
14
|
],
|
|
15
15
|
"mappings": "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",
|
|
16
|
-
"debugId": "
|
|
16
|
+
"debugId": "6A849ADF7E0345A464756E2164756E21",
|
|
17
17
|
"names": []
|
|
18
18
|
}
|