broods 0.11.0 → 0.12.0
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/account.d.ts +9 -0
- package/dist/cli/index.js +2 -2
- package/dist/index.d.ts +11 -1
- package/package.json +1 -1
package/dist/account.d.ts
CHANGED
|
@@ -82,6 +82,7 @@ interface AgentConfig {
|
|
|
82
82
|
denyTools?: string[];
|
|
83
83
|
skills?: AgentSkillsConfig;
|
|
84
84
|
subagent?: AgentSubagentConfig;
|
|
85
|
+
scheduler?: AgentSchedulerConfig;
|
|
85
86
|
policy?: AgentPolicyConfig;
|
|
86
87
|
publicAccess?: boolean;
|
|
87
88
|
[key: string]: unknown;
|
|
@@ -112,6 +113,14 @@ interface AgentSkillsConfig {
|
|
|
112
113
|
allowed?: string[];
|
|
113
114
|
[key: string]: unknown;
|
|
114
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Opt-in for the `schedule` tool. Off by default: a scheduled task starts
|
|
118
|
+
* billable agent runs long after the turn that asked for it.
|
|
119
|
+
*/
|
|
120
|
+
interface AgentSchedulerConfig {
|
|
121
|
+
enabled?: boolean;
|
|
122
|
+
[key: string]: unknown;
|
|
123
|
+
}
|
|
115
124
|
interface AgentSubagentConfig {
|
|
116
125
|
enabled?: boolean;
|
|
117
126
|
allowed?: string[];
|
package/dist/cli/index.js
CHANGED
|
@@ -11,7 +11,7 @@ export const defineCron = passthrough;
|
|
|
11
11
|
export const defineBroods = passthrough;
|
|
12
12
|
export const env = (name) => ({ __beeblastEnv: true, name });
|
|
13
13
|
export default {};
|
|
14
|
-
`,Ze=1e7,qa=20000000,Wa=200,zf=new Set(["node_modules",".git"]),jf=[/^\.env(?:\.|$)/i,/^id_(?:rsa|dsa|ecdsa|ed25519)(?:\.pub)?$/i,/\.(?:pem|key|p12|pfx)$/i],ko={onStart:"agent.started",onStepFinish:"agent.step.finished",onToolCall:"tool.call.started",onToolResult:"tool.result",onFinish:"agent.finished",onApproval:"agent.approval.required",onError:"agent.failed",onSubagentFinish:"subagent.task.finished",onMessageReceived:"channel.message.received",onMessageSending:"channel.message.sending"};async function Le(e={}){let t=e.cwd??process.cwd();te(t);let r=Cr(t,ce),o=await Uf(r),n=await Zf(o),a=await Lf(n,t,e.project),s=n.filter((f)=>X(f.value)).map((f)=>({exportName:f.exportName,file:f.file,resource:f.value})),i=s.map((f)=>f.resource);em(i),Qf(i);let u=rm(s,n);for(let f of i)Bf(f);for(let f of i)qf(f);for(let f of i)Wf(f);Vf(i),Gf(i);let c=tm(s),d=Df(a,e.stage??(e.useRuntimeStage===!1?void 0:nt()),e.command??"dev"),p=(await Promise.all(s.map((f)=>om(f,r)))).flat().sort((f,h)=>`${f.kind}:${f.name}`.localeCompare(`${h.kind}:${h.name}`));return{config:a,resources:i,resourceAliases:c,channels:u,manifest:{version:1,project:a.project,stage:d,resources:p}}}function Qa(e){let t=new Set;for(let r of e.resources)Or(r.config,t);return[...t].sort()}function Or(e,t){if(Array.isArray(e)){for(let r of e)Or(r,t);return}if(e&&typeof e==="object"){let r=e;if(r.__beeblastEnv===!0&&typeof r.name==="string"){t.add(r.name);return}for(let o of Object.values(r))Or(o,t)}}function Df(e,t,r){if(t)return t;let o=e.stages?.[r];if(o)return o;return r==="deploy"?"production":"development"}async function Uf(e){let t=[];async function r(o){let n=await Ha(o,{withFileTypes:!0});for(let a of n){let s=St(o,a.name);if(a.isDirectory()){if(a.name===Ce||a.name==="generated")continue;await r(s)}else if(a.isFile()&&a.name.endsWith(".ts"))t.push(s)}}return await r(e),t.sort((o,n)=>It(e,o).localeCompare(It(e,n)))}async function Zf(e){let t=[];for(let r of e){let n=await import(`${kf(r).href}?t=${Date.now()}`);t.push(...Object.entries(n).map(([a,s])=>({exportName:a,file:r,value:s})))}return t}async function Lf(e,t,r){let n=e.find((s)=>Ga(s.value))?.value?.config??{},a=r??process.env.BROODS_PROJECT??n.project??$m(Xa(Cr(t)));if(!a.trim())throw Error("Project name is required. Pass --project <name> or set BROODS_PROJECT.");return{...n,project:a}}var Va=new Set(["agent","harness","model","provider","session","hooks","channels","tools","denyTools","sandbox","workspaces","subagent","skills","policy","publicAccess"]),Ff={workspace:"workspaces",skill:"skills",policies:"policy",tool:"tools",channel:"channels",hook:"hooks",subagents:"subagent",sandboxes:"sandbox",systemPrompt:"agent",system:"agent"};function Bf(e){if(e.kind!=="agent")return;let t=e.config;for(let r of Object.keys(t)){if(Va.has(r))continue;let o=Ff[r],n=o?` Did you mean "${o}"?`:` Allowed keys: ${[...Va].sort().join(", ")}.`;throw Error(`Agent "${e.name}" has an unknown config key "${r}".${n}`)}}function qf(e){if(e.kind!=="workspace")return;let r=e.config.storage;if(r===void 0)return;if(!r||typeof r!=="object"||Array.isArray(r))throw Error(`Workspace "${e.name}" config.storage must be an object`);let o=r.provider;if(o===void 0||o==="s3")return;if(o==="vercel")throw Error(`Workspace "${e.name}" uses storage.provider "vercel", but Vercel Drive workspace storage is not supported yet. Use storage.provider "s3" or omit storage until Vercel Drive is wired.`);throw Error(`Workspace "${e.name}" config.storage.provider must be one of: s3`)}function Wf(e){if(e.kind!=="workspace")return;let t=e.config;if(typeof t.isolation==="string")throw Error(`Workspace "${e.name}" config.isolation no longer supports string modes; use isolation: true or omit it.`);if(t.isolation!==void 0&&typeof t.isolation!=="boolean")throw Error(`Workspace "${e.name}" config.isolation must be a boolean`)}function Vf(e){let t=new Map(e.filter((r)=>r.kind==="workspace").map((r)=>[r.name,r]));for(let r of e){if(r.kind!=="agent")continue;let o=r.config,n=o.channels;if(n!==void 0&&!Array.isArray(n))throw Error(`Agent "${r.name}" config.channels must be an array of channel definitions`);let a=Array.isArray(n)?n.filter(Kt):[],s=new Set;for(let d of a){let p=d.config,f=typeof p.id==="string"?p.id:void 0;if(f){if(s.has(f))throw Error(`Duplicate channel id: ${f}`);s.add(f)}if(d.workspaceScope)Jf(d.workspaceScope,`Agent "${r.name}" channel "${d.type}"`);if(d.config&&typeof d.config==="object"&&"workspaceIsolationScope"in d.config)throw Error(`Agent "${r.name}" channel "${d.type}" uses workspaceIsolationScope, which is no longer supported; use workspaceScope.`)}let u=(Array.isArray(o.workspaces)?o.workspaces.map((d)=>Kf(d,t)).filter((d)=>Boolean(d)):[]).filter((d)=>d.config.isolation===!0),c=a.filter((d)=>d.workspaceScope);if(c.length>0&&u.length===0){let d=c[0];throw Error(`Agent "${r.name}" channel "${d.type}" defines workspaceScope, but no attached workspace has isolation: true.`)}if(u.length>0){for(let d of a)if(!d.workspaceScope)throw Error(`Agent "${r.name}" attaches isolated workspace "${u[0].name}", but channel "${d.type}" does not define workspaceScope.`)}}}function Jf(e,t){if(!e)return;if(e.level==="channel"){if("alias"in e&&e.alias!==void 0)throw Error(`${t} workspaceScope.alias is only supported when workspaceScope.level is conversation`);return}if(e.level!=="conversation")throw Error(`${t} workspaceScope.level must be one of: channel, conversation`);if(!("alias"in e)||typeof e.alias!=="string"||e.alias.length===0)throw Error(`${t} workspaceScope.alias must be a non-empty string when workspaceScope.level is conversation`);if(!/^[A-Za-z0-9._-]+$/.test(e.alias))throw Error(`${t} workspaceScope.alias must use only letters, numbers, dots, underscores, or hyphens`)}function Kf(e,t){if(X(e)&&e.kind==="workspace")return e;if(typeof e==="string")return t.get(e);if(e&&typeof e==="object"&&"workspace"in e){let r=e.workspace;if(X(r)&&r.kind==="workspace")return r;if(typeof r==="string")return t.get(r)}return}function Gf(e){let t=new Map(e.filter((r)=>r.kind==="sandbox").map((r)=>[r.name,r]));for(let r of e){if(r.kind!=="agent")continue;let o=r.config,n=es(o.sandbox,t),a=o.workspaces;if(!Array.isArray(a))continue;for(let s of a){let i=Yf(s),u=Hf(s,n,t);if(!u||Xf(u))continue;throw Error(`Agent "${r.name}" workspace "${i}" uses sandbox "${u.name}" (${ts(u)}) which does not support S3 workspace mounts. Use lambda/sandbox, or daytona with options.mountAwsS3Buckets: true, or set this workspace ref to sandbox: null for read-only S3 access.`)}}}function es(e,t){if(X(e)&&e.kind==="sandbox")return e;if(typeof e==="string")return t.get(e);return}function Hf(e,t,r){if(e&&typeof e==="object"&&"sandbox"in e){let o=e.sandbox;if(o===null)return;return es(o,r)}return t}function Yf(e){if(X(e)&&e.kind==="workspace")return e.name;if(e&&typeof e==="object"&&"workspace"in e){let t=e.workspace;if(X(t))return t.name;if(typeof t==="string")return t}return"<unknown>"}function Xf(e){let t=ts(e);if(t==="lambda"||t==="sandbox")return!0;if(t!=="daytona")return!1;let r=e.config.options;return Boolean(r&&typeof r==="object"&&!Array.isArray(r)&&r.mountAwsS3Buckets===!0)}function ts(e){return typeof e.config.provider==="string"?e.config.provider:"sandbox"}function Qf(e){let t=new Set(e.filter((r)=>r.kind==="sandbox").map((r)=>r.name));for(let r of e){if(r.kind!=="agent")continue;let o=r.config.harness?.sandbox;if(X(o)&&o.kind==="sandbox"&&!t.has(o.name))throw Error(`Agent "${r.name}" harness references sandbox "${o.name}", but that sandbox is not exported from broods/`)}}function em(e){let t=new Set;for(let r of e){let o=`${r.kind}:${r.name}`;if(t.has(o))throw Error(`Duplicate resource: ${o}`);t.add(o)}}function tm(e){let t={},r=new Set;for(let{exportName:o,resource:n}of e){if(o==="default"||!$o(o))continue;let a=`${n.kind}:${o}`;if(r.has(a))throw Error(`Duplicate export alias for ${n.kind}: ${o}`);r.add(a),t[n.kind]??={},t[n.kind][n.name]=o}return t}function rm(e,t){let r=new Map;for(let s of t){if(!Kt(s.value)||s.exportName==="default"||!$o(s.exportName))continue;let i=r.get(s.value);if(i&&i!==s.exportName)throw Error(`Channel is exported more than once: ${i}, ${s.exportName}`);r.set(s.value,s.exportName)}let o=new Map,n=new Set,a=[];for(let{exportName:s,resource:i}of e){if(i.kind!=="agent")continue;let u=i.config.channels;if(u===void 0)continue;if(!Array.isArray(u))throw Error(`Agent "${i.name}" config.channels must be an array of channel definitions`);let c=new Set;for(let d of u){if(!Kt(d))throw Error(`Agent "${i.name}" config.channels must contain channel definitions`);let p=o.get(d);if(p&&p!==i.name)throw Error(`Channel ${d.type} is already attached to agent "${p}" and cannot also attach to "${i.name}"`);if(c.has(d.type))throw Error(`Agent "${i.name}" cannot configure more than one ${d.type} channel`);o.set(d,i.name),c.add(d.type);let f=s!=="default"&&$o(s)?s:i.name,h=r.get(d)??`${f}${rs(d.type)}Channel`;if(n.has(h))throw Error(`Duplicate channel export alias: ${h}`);n.add(h),a.push({alias:h,type:d.type,id:h,agentName:i.name})}}for(let[s,i]of r)if(!o.has(s))throw Error(`Channel "${i}" must be attached to exactly one agent`);return a.sort((s,i)=>s.alias.localeCompare(i.alias))}function rs(e){return e.charAt(0).toUpperCase()+e.slice(1)}function $o(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}async function om(e,t){let r=e.resource;if(r.kind==="agent"){let o=pm(r,t);return[...o.hookResource?[o.hookResource]:[],{kind:r.kind,name:r.name,...r.description?{description:r.description}:{},config:o.config}]}return[{kind:r.kind,name:r.name,...r.description?{description:r.description}:{},config:await nm(e,t)}]}async function nm(e,t){let r=e.resource;if(r.kind==="skill")return await vm(r.config,t);if(r.kind==="tool")return await ym(e,r.config,t);if(r.kind==="policy"){let o={...r.config};return o.version=o.version??1,Tt(o)}if(r.kind==="cron"){let o={...r.config},n=o.agent;if(o.agentId=X(n)?n.name:n,o.name=o.name??r.name,delete o.agent,typeof o.input==="string")o.events=[{role:"user",content:[{type:"text",text:o.input}]}],delete o.input;return Tt(o)}return Tt(r.config)}var Ja=["google","openai","anthropic","bedrock","vercel","minimax","custom"],am=new Set(["apiKey","base_url","baseURL","headers","organization","project","name","region","accessKeyId","secretAccessKey","sessionToken"]),sm=new Set(["activeTools","debug","inactiveTools","permissionMode","sandbox","startupTimeoutMs","type","webSearch"]),im=new Set(["enabled","level","subsystems"]);function lm(e){let t=e.replace(/[^a-z0-9]/gi,"").toLowerCase();if(t==="baseurl")return'"base_url" or "baseURL"';if(t==="apikey")return'"apiKey"';return""}function cm(e,t){if(t===void 0||t===null)return;if(typeof t!=="object"||Array.isArray(t))throw Error(`Agent "${e}" config.provider must be an object`);for(let[r,o]of Object.entries(t)){if(!Ja.includes(r))throw Error(`Agent "${e}" config.provider.${r} is not a supported provider (expected one of: ${Ja.join(", ")})`);if(typeof o!=="object"||o===null||Array.isArray(o))throw Error(`Agent "${e}" config.provider.${r} must be an object`);let n=o;for(let a of Object.keys(n)){if(am.has(a))continue;let s=lm(a);throw Error(`Agent "${e}" config.provider.${r} has unknown option "${a}"${s?` — did you mean ${s}?`:""}`)}if(r==="custom"&&n.base_url===void 0&&n.baseURL===void 0)throw Error(`Agent "${e}" config.provider.custom.base_url is required (use "base_url" or "baseURL")`)}}function um(e,t){if(t===void 0||t===null)return;if(typeof t!=="object"||Array.isArray(t))throw Error(`Agent "${e}" config.harness must be an object`);let r=t;for(let o of Object.keys(r))if(!sm.has(o))throw Error(`Agent "${e}" config.harness has unknown option "${o}"`);if(r.type!=="claude-code"&&r.type!=="codex"&&r.type!=="deepagents"&&r.type!=="opencode"&&r.type!=="pi")throw Error(`Agent "${e}" config.harness.type must be claude-code, codex, deepagents, opencode, or pi`);if(r.sandbox===void 0)throw Error(`Agent "${e}" config.harness.sandbox is required for ${r.type}`);if(r.sandbox!==void 0&&!(typeof r.sandbox==="string"||X(r.sandbox)&&r.sandbox.kind==="sandbox"))throw Error(`Agent "${e}" config.harness.sandbox must be a defineSandbox resource or sandbox name`);if(r.permissionMode!==void 0&&r.permissionMode!=="allow-reads"&&r.permissionMode!=="allow-edits"&&r.permissionMode!=="allow-all")throw Error(`Agent "${e}" config.harness.permissionMode must be allow-reads, allow-edits, or allow-all`);if(r.type==="codex"&&r.permissionMode!==void 0&&r.permissionMode!=="allow-all")throw Error(`Agent "${e}" config.harness.permissionMode must be allow-all for codex`);if(r.startupTimeoutMs!==void 0&&(typeof r.startupTimeoutMs!=="number"||!Number.isSafeInteger(r.startupTimeoutMs)||r.startupTimeoutMs<1||r.startupTimeoutMs>600000))throw Error(`Agent "${e}" config.harness.startupTimeoutMs must be an integer from 1 to 600000`);if(r.webSearch!==void 0&&typeof r.webSearch!=="boolean")throw Error(`Agent "${e}" config.harness.webSearch must be a boolean`);if(r.type!=="codex"&&r.webSearch!==void 0)throw Error(`Agent "${e}" config.harness.webSearch is only supported by codex`);if(r.type==="pi"&&r.startupTimeoutMs!==void 0)throw Error(`Agent "${e}" config.harness.startupTimeoutMs is not supported by pi`);if(Mo(e,r.activeTools,"activeTools"),Mo(e,r.inactiveTools,"inactiveTools"),r.activeTools!==void 0&&r.inactiveTools!==void 0)throw Error(`Agent "${e}" config.harness must use either activeTools or inactiveTools, not both`);dm(e,r.debug)}function dm(e,t){if(t===void 0)return;if(typeof t!=="object"||t===null||Array.isArray(t))throw Error(`Agent "${e}" config.harness.debug must be an object`);let r=t;for(let o of Object.keys(r))if(!im.has(o))throw Error(`Agent "${e}" config.harness.debug has unknown option "${o}"`);if(r.enabled!==void 0&&typeof r.enabled!=="boolean")throw Error(`Agent "${e}" config.harness.debug.enabled must be a boolean`);if(r.level!==void 0&&r.level!=="error"&&r.level!=="warn"&&r.level!=="info"&&r.level!=="debug"&&r.level!=="trace")throw Error(`Agent "${e}" config.harness.debug.level must be error, warn, info, debug, or trace`);Mo(e,r.subsystems,"debug.subsystems")}function Mo(e,t,r){if(t!==void 0&&(!Array.isArray(t)||!t.every((o)=>typeof o==="string"&&o.trim().length>0)))throw Error(`Agent "${e}" config.harness.${r} must be an array of non-empty strings`)}function pm(e,t){let r={...e.config};if(cm(e.name,r.provider),um(e.name,r.harness),r.harness&&typeof r.harness==="object"&&!Array.isArray(r.harness)){let n={...r.harness};if(r.sandbox!==void 0)throw Error(`Agent "${e.name}" must configure the AI SDK harness sandbox on defineHarness, not defineAgent`);r.sandbox=X(n.sandbox)?n.sandbox.name:n.sandbox,delete n.sandbox,r.harness=n}let o=fm(e.name,r.hooks);if(o)r.hooks=o.agentHooksConfig;else if(r.hooks!==void 0)r.hooks=os(r.hooks,e.name);if(r.channels!==void 0){if(!Array.isArray(r.channels))throw Error(`Agent "${e.name}" config.channels must be an array of channel definitions`);r.channels=Object.fromEntries(r.channels.map((n)=>{if(!Kt(n))throw Error(`Agent "${e.name}" config.channels must contain channel definitions`);let a=`${e.name}${rs(n.type)}Channel`;return[n.type,{id:a,...n.config}]}))}if(X(r.sandbox))r.sandbox=r.sandbox.name;if(Array.isArray(r.workspaces))r.workspaces=r.workspaces.map((n)=>wm(n,e.name));if(r.policy!==void 0){let n=gm(r.policy,e.name);if(n)r.policy=n;else delete r.policy}return{config:Tt(r),...o?.hookResource?{hookResource:o.hookResource}:{}}}function fm(e,t){if(t===void 0)return;if(!t||typeof t!=="object"||Array.isArray(t))throw Error(`Agent "${e}" config.hooks must be an object`);let r=t,o=Object.keys(ko).flatMap((c)=>{let d=r[c];if(d===void 0)return[];if(typeof d!=="function")throw Error(`Agent "${e}" config.hooks.${c} must be a function`);return[{name:c,event:ko[c],source:mm(d.toString())}]});if(o.length===0)return;let n=`${e}-hooks`,a=hm(e,o),s=Buffer.byteLength(a);if(s>Ze)throw Error(`Agent "${e}" hook bundle is too large (${s} bytes, max ${Ze})`);let i=o.map((c)=>c.event),u=os(r,e);return u.code=[{hookId:n}],{agentHooksConfig:u,hookResource:{kind:"hook",name:n,description:`Inline hooks for agent ${e}`,config:{events:i,bundle:a,sha256:Ro(a)}}}}function os(e,t){if(!e||typeof e!=="object"||Array.isArray(e))throw Error(`Agent "${t}" config.hooks must be an object`);let r=Object.entries(e);for(let[n]of r){if(n==="webhooks"||n in ko)continue;throw Error(`Agent "${t}" config.hooks.${n} is not supported. Use inline hook callbacks or hooks.webhooks.`)}return Object.fromEntries(r.filter(([n])=>n==="webhooks"))}function mm(e){let t=e.trim();if(/^(async\s+)?function\b/.test(t)||/^(async\s*)?\(/.test(t)||/^(async\s+)?[A-Za-z_$][\w$]*\s*=>/.test(t))return t;if(/^(async\s+)?[A-Za-z_$][\w$]*\s*\(/.test(t))return t.replace(/^(async\s+)?/,"$1function ");return t}function hm(e,t){let r=`export default {
|
|
14
|
+
`,Ze=1e7,qa=20000000,Wa=200,zf=new Set(["node_modules",".git"]),jf=[/^\.env(?:\.|$)/i,/^id_(?:rsa|dsa|ecdsa|ed25519)(?:\.pub)?$/i,/\.(?:pem|key|p12|pfx)$/i],ko={onStart:"agent.started",onStepFinish:"agent.step.finished",onToolCall:"tool.call.started",onToolResult:"tool.result",onFinish:"agent.finished",onApproval:"agent.approval.required",onError:"agent.failed",onSubagentFinish:"subagent.task.finished",onMessageReceived:"channel.message.received",onMessageSending:"channel.message.sending"};async function Le(e={}){let t=e.cwd??process.cwd();te(t);let r=Cr(t,ce),o=await Uf(r),n=await Zf(o),a=await Lf(n,t,e.project),s=n.filter((f)=>X(f.value)).map((f)=>({exportName:f.exportName,file:f.file,resource:f.value})),i=s.map((f)=>f.resource);em(i),Qf(i);let u=rm(s,n);for(let f of i)Bf(f);for(let f of i)qf(f);for(let f of i)Wf(f);Vf(i),Gf(i);let c=tm(s),d=Df(a,e.stage??(e.useRuntimeStage===!1?void 0:nt()),e.command??"dev"),p=(await Promise.all(s.map((f)=>om(f,r)))).flat().sort((f,h)=>`${f.kind}:${f.name}`.localeCompare(`${h.kind}:${h.name}`));return{config:a,resources:i,resourceAliases:c,channels:u,manifest:{version:1,project:a.project,stage:d,resources:p}}}function Qa(e){let t=new Set;for(let r of e.resources)Or(r.config,t);return[...t].sort()}function Or(e,t){if(Array.isArray(e)){for(let r of e)Or(r,t);return}if(e&&typeof e==="object"){let r=e;if(r.__beeblastEnv===!0&&typeof r.name==="string"){t.add(r.name);return}for(let o of Object.values(r))Or(o,t)}}function Df(e,t,r){if(t)return t;let o=e.stages?.[r];if(o)return o;return r==="deploy"?"production":"development"}async function Uf(e){let t=[];async function r(o){let n=await Ha(o,{withFileTypes:!0});for(let a of n){let s=St(o,a.name);if(a.isDirectory()){if(a.name===Ce||a.name==="generated")continue;await r(s)}else if(a.isFile()&&a.name.endsWith(".ts"))t.push(s)}}return await r(e),t.sort((o,n)=>It(e,o).localeCompare(It(e,n)))}async function Zf(e){let t=[];for(let r of e){let n=await import(`${kf(r).href}?t=${Date.now()}`);t.push(...Object.entries(n).map(([a,s])=>({exportName:a,file:r,value:s})))}return t}async function Lf(e,t,r){let n=e.find((s)=>Ga(s.value))?.value?.config??{},a=r??process.env.BROODS_PROJECT??n.project??$m(Xa(Cr(t)));if(!a.trim())throw Error("Project name is required. Pass --project <name> or set BROODS_PROJECT.");return{...n,project:a}}var Va=new Set(["agent","harness","model","provider","session","hooks","channels","tools","denyTools","sandbox","workspaces","subagent","skills","scheduler","policy","publicAccess"]),Ff={workspace:"workspaces",skill:"skills",policies:"policy",tool:"tools",channel:"channels",hook:"hooks",subagents:"subagent",sandboxes:"sandbox",systemPrompt:"agent",system:"agent"};function Bf(e){if(e.kind!=="agent")return;let t=e.config;for(let r of Object.keys(t)){if(Va.has(r))continue;let o=Ff[r],n=o?` Did you mean "${o}"?`:` Allowed keys: ${[...Va].sort().join(", ")}.`;throw Error(`Agent "${e.name}" has an unknown config key "${r}".${n}`)}}function qf(e){if(e.kind!=="workspace")return;let r=e.config.storage;if(r===void 0)return;if(!r||typeof r!=="object"||Array.isArray(r))throw Error(`Workspace "${e.name}" config.storage must be an object`);let o=r.provider;if(o===void 0||o==="s3")return;if(o==="vercel")throw Error(`Workspace "${e.name}" uses storage.provider "vercel", but Vercel Drive workspace storage is not supported yet. Use storage.provider "s3" or omit storage until Vercel Drive is wired.`);throw Error(`Workspace "${e.name}" config.storage.provider must be one of: s3`)}function Wf(e){if(e.kind!=="workspace")return;let t=e.config;if(typeof t.isolation==="string")throw Error(`Workspace "${e.name}" config.isolation no longer supports string modes; use isolation: true or omit it.`);if(t.isolation!==void 0&&typeof t.isolation!=="boolean")throw Error(`Workspace "${e.name}" config.isolation must be a boolean`)}function Vf(e){let t=new Map(e.filter((r)=>r.kind==="workspace").map((r)=>[r.name,r]));for(let r of e){if(r.kind!=="agent")continue;let o=r.config,n=o.channels;if(n!==void 0&&!Array.isArray(n))throw Error(`Agent "${r.name}" config.channels must be an array of channel definitions`);let a=Array.isArray(n)?n.filter(Kt):[],s=new Set;for(let d of a){let p=d.config,f=typeof p.id==="string"?p.id:void 0;if(f){if(s.has(f))throw Error(`Duplicate channel id: ${f}`);s.add(f)}if(d.workspaceScope)Jf(d.workspaceScope,`Agent "${r.name}" channel "${d.type}"`);if(d.config&&typeof d.config==="object"&&"workspaceIsolationScope"in d.config)throw Error(`Agent "${r.name}" channel "${d.type}" uses workspaceIsolationScope, which is no longer supported; use workspaceScope.`)}let u=(Array.isArray(o.workspaces)?o.workspaces.map((d)=>Kf(d,t)).filter((d)=>Boolean(d)):[]).filter((d)=>d.config.isolation===!0),c=a.filter((d)=>d.workspaceScope);if(c.length>0&&u.length===0){let d=c[0];throw Error(`Agent "${r.name}" channel "${d.type}" defines workspaceScope, but no attached workspace has isolation: true.`)}if(u.length>0){for(let d of a)if(!d.workspaceScope)throw Error(`Agent "${r.name}" attaches isolated workspace "${u[0].name}", but channel "${d.type}" does not define workspaceScope.`)}}}function Jf(e,t){if(!e)return;if(e.level==="channel"){if("alias"in e&&e.alias!==void 0)throw Error(`${t} workspaceScope.alias is only supported when workspaceScope.level is conversation`);return}if(e.level!=="conversation")throw Error(`${t} workspaceScope.level must be one of: channel, conversation`);if(!("alias"in e)||typeof e.alias!=="string"||e.alias.length===0)throw Error(`${t} workspaceScope.alias must be a non-empty string when workspaceScope.level is conversation`);if(!/^[A-Za-z0-9._-]+$/.test(e.alias))throw Error(`${t} workspaceScope.alias must use only letters, numbers, dots, underscores, or hyphens`)}function Kf(e,t){if(X(e)&&e.kind==="workspace")return e;if(typeof e==="string")return t.get(e);if(e&&typeof e==="object"&&"workspace"in e){let r=e.workspace;if(X(r)&&r.kind==="workspace")return r;if(typeof r==="string")return t.get(r)}return}function Gf(e){let t=new Map(e.filter((r)=>r.kind==="sandbox").map((r)=>[r.name,r]));for(let r of e){if(r.kind!=="agent")continue;let o=r.config,n=es(o.sandbox,t),a=o.workspaces;if(!Array.isArray(a))continue;for(let s of a){let i=Yf(s),u=Hf(s,n,t);if(!u||Xf(u))continue;throw Error(`Agent "${r.name}" workspace "${i}" uses sandbox "${u.name}" (${ts(u)}) which does not support S3 workspace mounts. Use lambda/sandbox, or daytona with options.mountAwsS3Buckets: true, or set this workspace ref to sandbox: null for read-only S3 access.`)}}}function es(e,t){if(X(e)&&e.kind==="sandbox")return e;if(typeof e==="string")return t.get(e);return}function Hf(e,t,r){if(e&&typeof e==="object"&&"sandbox"in e){let o=e.sandbox;if(o===null)return;return es(o,r)}return t}function Yf(e){if(X(e)&&e.kind==="workspace")return e.name;if(e&&typeof e==="object"&&"workspace"in e){let t=e.workspace;if(X(t))return t.name;if(typeof t==="string")return t}return"<unknown>"}function Xf(e){let t=ts(e);if(t==="lambda"||t==="sandbox")return!0;if(t!=="daytona")return!1;let r=e.config.options;return Boolean(r&&typeof r==="object"&&!Array.isArray(r)&&r.mountAwsS3Buckets===!0)}function ts(e){return typeof e.config.provider==="string"?e.config.provider:"sandbox"}function Qf(e){let t=new Set(e.filter((r)=>r.kind==="sandbox").map((r)=>r.name));for(let r of e){if(r.kind!=="agent")continue;let o=r.config.harness?.sandbox;if(X(o)&&o.kind==="sandbox"&&!t.has(o.name))throw Error(`Agent "${r.name}" harness references sandbox "${o.name}", but that sandbox is not exported from broods/`)}}function em(e){let t=new Set;for(let r of e){let o=`${r.kind}:${r.name}`;if(t.has(o))throw Error(`Duplicate resource: ${o}`);t.add(o)}}function tm(e){let t={},r=new Set;for(let{exportName:o,resource:n}of e){if(o==="default"||!$o(o))continue;let a=`${n.kind}:${o}`;if(r.has(a))throw Error(`Duplicate export alias for ${n.kind}: ${o}`);r.add(a),t[n.kind]??={},t[n.kind][n.name]=o}return t}function rm(e,t){let r=new Map;for(let s of t){if(!Kt(s.value)||s.exportName==="default"||!$o(s.exportName))continue;let i=r.get(s.value);if(i&&i!==s.exportName)throw Error(`Channel is exported more than once: ${i}, ${s.exportName}`);r.set(s.value,s.exportName)}let o=new Map,n=new Set,a=[];for(let{exportName:s,resource:i}of e){if(i.kind!=="agent")continue;let u=i.config.channels;if(u===void 0)continue;if(!Array.isArray(u))throw Error(`Agent "${i.name}" config.channels must be an array of channel definitions`);let c=new Set;for(let d of u){if(!Kt(d))throw Error(`Agent "${i.name}" config.channels must contain channel definitions`);let p=o.get(d);if(p&&p!==i.name)throw Error(`Channel ${d.type} is already attached to agent "${p}" and cannot also attach to "${i.name}"`);if(c.has(d.type))throw Error(`Agent "${i.name}" cannot configure more than one ${d.type} channel`);o.set(d,i.name),c.add(d.type);let f=s!=="default"&&$o(s)?s:i.name,h=r.get(d)??`${f}${rs(d.type)}Channel`;if(n.has(h))throw Error(`Duplicate channel export alias: ${h}`);n.add(h),a.push({alias:h,type:d.type,id:h,agentName:i.name})}}for(let[s,i]of r)if(!o.has(s))throw Error(`Channel "${i}" must be attached to exactly one agent`);return a.sort((s,i)=>s.alias.localeCompare(i.alias))}function rs(e){return e.charAt(0).toUpperCase()+e.slice(1)}function $o(e){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(e)}async function om(e,t){let r=e.resource;if(r.kind==="agent"){let o=pm(r,t);return[...o.hookResource?[o.hookResource]:[],{kind:r.kind,name:r.name,...r.description?{description:r.description}:{},config:o.config}]}return[{kind:r.kind,name:r.name,...r.description?{description:r.description}:{},config:await nm(e,t)}]}async function nm(e,t){let r=e.resource;if(r.kind==="skill")return await vm(r.config,t);if(r.kind==="tool")return await ym(e,r.config,t);if(r.kind==="policy"){let o={...r.config};return o.version=o.version??1,Tt(o)}if(r.kind==="cron"){let o={...r.config},n=o.agent;if(o.agentId=X(n)?n.name:n,o.name=o.name??r.name,delete o.agent,typeof o.input==="string")o.events=[{role:"user",content:[{type:"text",text:o.input}]}],delete o.input;return Tt(o)}return Tt(r.config)}var Ja=["google","openai","anthropic","bedrock","vercel","minimax","custom"],am=new Set(["apiKey","base_url","baseURL","headers","organization","project","name","region","accessKeyId","secretAccessKey","sessionToken"]),sm=new Set(["activeTools","debug","inactiveTools","permissionMode","sandbox","startupTimeoutMs","type","webSearch"]),im=new Set(["enabled","level","subsystems"]);function lm(e){let t=e.replace(/[^a-z0-9]/gi,"").toLowerCase();if(t==="baseurl")return'"base_url" or "baseURL"';if(t==="apikey")return'"apiKey"';return""}function cm(e,t){if(t===void 0||t===null)return;if(typeof t!=="object"||Array.isArray(t))throw Error(`Agent "${e}" config.provider must be an object`);for(let[r,o]of Object.entries(t)){if(!Ja.includes(r))throw Error(`Agent "${e}" config.provider.${r} is not a supported provider (expected one of: ${Ja.join(", ")})`);if(typeof o!=="object"||o===null||Array.isArray(o))throw Error(`Agent "${e}" config.provider.${r} must be an object`);let n=o;for(let a of Object.keys(n)){if(am.has(a))continue;let s=lm(a);throw Error(`Agent "${e}" config.provider.${r} has unknown option "${a}"${s?` — did you mean ${s}?`:""}`)}if(r==="custom"&&n.base_url===void 0&&n.baseURL===void 0)throw Error(`Agent "${e}" config.provider.custom.base_url is required (use "base_url" or "baseURL")`)}}function um(e,t){if(t===void 0||t===null)return;if(typeof t!=="object"||Array.isArray(t))throw Error(`Agent "${e}" config.harness must be an object`);let r=t;for(let o of Object.keys(r))if(!sm.has(o))throw Error(`Agent "${e}" config.harness has unknown option "${o}"`);if(r.type!=="claude-code"&&r.type!=="codex"&&r.type!=="deepagents"&&r.type!=="opencode"&&r.type!=="pi")throw Error(`Agent "${e}" config.harness.type must be claude-code, codex, deepagents, opencode, or pi`);if(r.sandbox===void 0)throw Error(`Agent "${e}" config.harness.sandbox is required for ${r.type}`);if(r.sandbox!==void 0&&!(typeof r.sandbox==="string"||X(r.sandbox)&&r.sandbox.kind==="sandbox"))throw Error(`Agent "${e}" config.harness.sandbox must be a defineSandbox resource or sandbox name`);if(r.permissionMode!==void 0&&r.permissionMode!=="allow-reads"&&r.permissionMode!=="allow-edits"&&r.permissionMode!=="allow-all")throw Error(`Agent "${e}" config.harness.permissionMode must be allow-reads, allow-edits, or allow-all`);if(r.type==="codex"&&r.permissionMode!==void 0&&r.permissionMode!=="allow-all")throw Error(`Agent "${e}" config.harness.permissionMode must be allow-all for codex`);if(r.startupTimeoutMs!==void 0&&(typeof r.startupTimeoutMs!=="number"||!Number.isSafeInteger(r.startupTimeoutMs)||r.startupTimeoutMs<1||r.startupTimeoutMs>600000))throw Error(`Agent "${e}" config.harness.startupTimeoutMs must be an integer from 1 to 600000`);if(r.webSearch!==void 0&&typeof r.webSearch!=="boolean")throw Error(`Agent "${e}" config.harness.webSearch must be a boolean`);if(r.type!=="codex"&&r.webSearch!==void 0)throw Error(`Agent "${e}" config.harness.webSearch is only supported by codex`);if(r.type==="pi"&&r.startupTimeoutMs!==void 0)throw Error(`Agent "${e}" config.harness.startupTimeoutMs is not supported by pi`);if(Mo(e,r.activeTools,"activeTools"),Mo(e,r.inactiveTools,"inactiveTools"),r.activeTools!==void 0&&r.inactiveTools!==void 0)throw Error(`Agent "${e}" config.harness must use either activeTools or inactiveTools, not both`);dm(e,r.debug)}function dm(e,t){if(t===void 0)return;if(typeof t!=="object"||t===null||Array.isArray(t))throw Error(`Agent "${e}" config.harness.debug must be an object`);let r=t;for(let o of Object.keys(r))if(!im.has(o))throw Error(`Agent "${e}" config.harness.debug has unknown option "${o}"`);if(r.enabled!==void 0&&typeof r.enabled!=="boolean")throw Error(`Agent "${e}" config.harness.debug.enabled must be a boolean`);if(r.level!==void 0&&r.level!=="error"&&r.level!=="warn"&&r.level!=="info"&&r.level!=="debug"&&r.level!=="trace")throw Error(`Agent "${e}" config.harness.debug.level must be error, warn, info, debug, or trace`);Mo(e,r.subsystems,"debug.subsystems")}function Mo(e,t,r){if(t!==void 0&&(!Array.isArray(t)||!t.every((o)=>typeof o==="string"&&o.trim().length>0)))throw Error(`Agent "${e}" config.harness.${r} must be an array of non-empty strings`)}function pm(e,t){let r={...e.config};if(cm(e.name,r.provider),um(e.name,r.harness),r.harness&&typeof r.harness==="object"&&!Array.isArray(r.harness)){let n={...r.harness};if(r.sandbox!==void 0)throw Error(`Agent "${e.name}" must configure the AI SDK harness sandbox on defineHarness, not defineAgent`);r.sandbox=X(n.sandbox)?n.sandbox.name:n.sandbox,delete n.sandbox,r.harness=n}let o=fm(e.name,r.hooks);if(o)r.hooks=o.agentHooksConfig;else if(r.hooks!==void 0)r.hooks=os(r.hooks,e.name);if(r.channels!==void 0){if(!Array.isArray(r.channels))throw Error(`Agent "${e.name}" config.channels must be an array of channel definitions`);r.channels=Object.fromEntries(r.channels.map((n)=>{if(!Kt(n))throw Error(`Agent "${e.name}" config.channels must contain channel definitions`);let a=`${e.name}${rs(n.type)}Channel`;return[n.type,{id:a,...n.config}]}))}if(X(r.sandbox))r.sandbox=r.sandbox.name;if(Array.isArray(r.workspaces))r.workspaces=r.workspaces.map((n)=>wm(n,e.name));if(r.policy!==void 0){let n=gm(r.policy,e.name);if(n)r.policy=n;else delete r.policy}return{config:Tt(r),...o?.hookResource?{hookResource:o.hookResource}:{}}}function fm(e,t){if(t===void 0)return;if(!t||typeof t!=="object"||Array.isArray(t))throw Error(`Agent "${e}" config.hooks must be an object`);let r=t,o=Object.keys(ko).flatMap((c)=>{let d=r[c];if(d===void 0)return[];if(typeof d!=="function")throw Error(`Agent "${e}" config.hooks.${c} must be a function`);return[{name:c,event:ko[c],source:mm(d.toString())}]});if(o.length===0)return;let n=`${e}-hooks`,a=hm(e,o),s=Buffer.byteLength(a);if(s>Ze)throw Error(`Agent "${e}" hook bundle is too large (${s} bytes, max ${Ze})`);let i=o.map((c)=>c.event),u=os(r,e);return u.code=[{hookId:n}],{agentHooksConfig:u,hookResource:{kind:"hook",name:n,description:`Inline hooks for agent ${e}`,config:{events:i,bundle:a,sha256:Ro(a)}}}}function os(e,t){if(!e||typeof e!=="object"||Array.isArray(e))throw Error(`Agent "${t}" config.hooks must be an object`);let r=Object.entries(e);for(let[n]of r){if(n==="webhooks"||n in ko)continue;throw Error(`Agent "${t}" config.hooks.${n} is not supported. Use inline hook callbacks or hooks.webhooks.`)}return Object.fromEntries(r.filter(([n])=>n==="webhooks"))}function mm(e){let t=e.trim();if(/^(async\s+)?function\b/.test(t)||/^(async\s*)?\(/.test(t)||/^(async\s+)?[A-Za-z_$][\w$]*\s*=>/.test(t))return t;if(/^(async\s+)?[A-Za-z_$][\w$]*\s*\(/.test(t))return t.replace(/^(async\s+)?/,"$1function ");return t}function hm(e,t){let r=`export default {
|
|
15
15
|
${t.map((o)=>` ${JSON.stringify(o.event)}: ${o.source},`).join(`
|
|
16
16
|
`)}
|
|
17
17
|
};
|
|
@@ -151,7 +151,7 @@ ${e.errorText}`};case"output-denied":return{kind:"error",title:`Tool Denied · $
|
|
|
151
151
|
Reason: ${(a=e.approval.reason)!=null?a:"denied"}`}}}function $p(e,t,r,o){switch(r){case"collapsed":return!0;case"auto-collapsed":return e.parts.slice(t+1).some((n)=>nx(n,o));case"full":case"hidden":return!1}}function nx(e,t){switch(e.type){case"text":return e.text.trim().length>0;case"reasoning":return t.reasoning!=="hidden"&&e.text.trim().length>0;default:return ie(e)&&t.tools!=="hidden"}}function ax(e){switch(e.type){case"text-start":case"text-delta":case"reasoning-start":case"reasoning-delta":case"tool-input-start":case"tool-input-delta":return!0;default:return!1}}function sx(e,{hasPendingToolResults:t}){switch(e.type){case"start-step":return t?Ep:_r;case"tool-output-available":case"tool-output-error":case"tool-output-denied":return Ep;case"tool-input-available":return kp;case"tool-approval-response":return e.approved?kp:void 0;default:return}}function ix(e){switch(e.type){case"tool-output-available":case"tool-output-error":case"tool-output-denied":return!0;default:return!1}}function lx(e){switch(e.state){case"input-streaming":return"waiting";case"approval-requested":return"approval requested";case"input-available":return"executing";case"approval-responded":return e.approval.approved?"executing":"denied";case"output-available":case"output-error":return"done";case"output-denied":return"denied"}}function Mp(e){if(typeof e==="string")return e;return JSON.stringify(e,null,2)}function cx(e){var t;return`tool ${(t=e.title)!=null?t:e.toolName}`}function ux(e,t){return`${e}:${t}`}function dx(e){if(e instanceof ReadableStream)return e;return new ReadableStream({async start(t){try{for await(let r of e)t.enqueue(r);t.close()}catch(r){t.error(r)}}})}async function*px(e){if(e instanceof ReadableStream){let t=e.getReader();try{while(!0){let{done:r,value:o}=await t.read();if(r)return;yield o}}finally{t.releaseLock()}return}yield*e}function Jp(e,t){if(e.cache&&Kp(e,e.cache,t))return e.cache.lines;let r=fx(e,t);return e.cache={width:t,kind:e.kind,title:e.title,rightTitle:e.rightTitle,content:e.content,collapsed:e.collapsed===!0,lines:r},r}function Kp(e,t,r=t.width){return t.width===r&&t.kind===e.kind&&t.title===e.title&&t.rightTitle===e.rightTitle&&t.content===e.content&&t.collapsed===(e.collapsed===!0)}function fx(e,t){let r=Xb[e.kind],o=Math.max(1,t-4),n=` ${e.title} `,a=e.rightTitle?` ${e.rightTitle} `:"";if(e.collapsed){let p=Math.max(0,t-2-n.length-a.length),f=`${r.color}╭${n}${r.border.repeat(p)}${a}╮${me.reset}`,h=`${r.color}╰${r.border.repeat(Math.max(0,t-2))}╯${me.reset}`;return[f,h]}let s=Math.max(0,t-2-n.length-a.length),i=`${r.color}╭${n}${r.border.repeat(s)}${a}╮${me.reset}`,u=`${r.color}╰${r.border.repeat(Math.max(0,t-2))}╯${me.reset}`,d=(e.content.length>0?Nb(e.content):me.dim+"(streaming...)"+me.reset).split(`
|
|
152
152
|
`).flatMap((p)=>hx(p,o));return[i,...d.map((p)=>mx(p,o,r.color)),u]}function mx(e,t,r){let o=Zt(e,t),n=" ".repeat(Math.max(0,t-Xe(o)));return`${r}│${me.reset} ${o}${n} ${r}│${me.reset}`}function hx(e,t){if(e.length===0)return[""];let r=[],o=e;while(Xe(o)>t){let n=gx(o,t);r.push(o.slice(0,n).trimEnd()),o=o.slice(n).trimStart()}return r.push(o),r}function gx(e,t){let o=Zt(e,t+1).lastIndexOf(" ");if(o>0)return o;return Zt(e,t).length}function vx(e){var t,r;let o="usage"in e?e.usage:void 0,n="messageMetadata"in e?(t=e.messageMetadata)==null?void 0:t.usage:void 0,a="messageMetadata"in e?(r=e.messageMetadata)==null?void 0:r.performance:void 0;return{totalTokens:Gp(o!=null?o:n),outputTokens:_a(o!=null?o:n),outputTokensPerSecond:a==null?void 0:a.outputTokensPerSecond}}function yx(e){var t;let r=e;return{totalTokens:Gp(r==null?void 0:r.usage),outputTokens:_a(r==null?void 0:r.usage),outputTokensPerSecond:(t=r==null?void 0:r.performance)==null?void 0:t.outputTokensPerSecond}}function Gp(e){let t=e==null?void 0:e.totalTokens;if(typeof t==="number")return t;if(typeof(t==null?void 0:t.total)==="number")return t.total;let r=wx(e),o=_a(e);if(r!=null&&o!=null)return r+o;return}function wx(e){let t=e==null?void 0:e.inputTokens;if(typeof t==="number")return t;if(typeof(t==null?void 0:t.total)==="number")return t.total;return e==null?void 0:e.promptTokens}function _a(e){let t=e==null?void 0:e.outputTokens;if(typeof t==="number")return t;if(typeof(t==null?void 0:t.total)==="number")return t.total;return e==null?void 0:e.completionTokens}function Hp(e,t){if(e==null)return;let r=`${e.toLocaleString()} ${e===1?"token":"tokens"}`,o=bx(e,t);return o==null?r:`${r} ${o}`}function bx(e,t){if(t==null||t<=0||!Number.isFinite(t))return;return`${Math.round(e/t*100).toLocaleString()}%`}function xx(e,t){if(t==="outputTokensPerSecond")return _x(e.outputTokensPerSecond);return Hp(e.outputTokens)}function _x(e){if(e==null)return;return`${Sx(e)} tok/s`}function Sx(e){return Number.isInteger(e)?e.toLocaleString():e.toLocaleString(void 0,{maximumFractionDigits:1})}function bo(e){let t=e.toString("utf8");switch(t){case"\f":return{type:"ctrl-l"};case"\x03":return{type:"ctrl-c"};case"\x1B":return{type:"escape"};case"\r":case`
|
|
153
153
|
`:return{type:"enter"};case"":case"\b":return{type:"backspace"};case"\x1B[A":return{type:"up"};case"\x1B[B":return{type:"down"};case"\x1B[5~":return{type:"page-up"};case"\x1B[6~":return{type:"page-down"};default:if(t>=" "&&t!=="")return{type:"character",value:t};return{type:"ignore"}}}var Tx="outputTokensPerSecond",Ix=class{constructor(e){this.chatId=Pt();var t,r,o,n;this.agent=e.agent,this.transport=e.transport,this.renderer=(t=kx(e))!=null?t:Ex(e),this.title=e.title,this.tools=(r=e.tools)!=null?r:"auto-collapsed",this.reasoning=(o=e.reasoning)!=null?o:"auto-collapsed",this.responseStatistics=(n=e.responseStatistics)!=null?n:Tx,this.contextSize=e.contextSize,this.sandbox=e.sandbox}async run(){let e=this.title,t=[],r=0,o=()=>`message-${++r}`,n,a=!1,s=!1;while(!0){if(!s){if(n==null){if(!this.renderer.readPrompt){if(a)return;throw Error("No prompt was provided and the renderer does not support prompt input.")}try{n=await this.renderer.readPrompt({title:e})}catch(u){if(Pp(u))return;throw u}if(n==null)return}t.push(Rx(o(),n)),a=!0}let i=await this.streamMessages([...t],o);try{let u=await this.renderer.renderStream(i,{title:e,submittedPrompt:n,continueSession:Boolean(this.renderer.readPrompt),tools:this.tools,reasoning:this.reasoning,responseStatistics:this.responseStatistics,contextSize:this.contextSize,waitForExit:!1});if(u&&u.parts.length>0){let c=Ax(u);if(c.length>0){if(!this.renderer.readToolApproval)throw Error("Tool approval was requested, but the renderer does not support tool approval input.");for(let d of c){let p=await this.renderer.readToolApproval(d,{title:e});Cx(u,d,p)}Ap(t,u,s),s=!0,n=void 0;continue}Ap(t,u,s)}}catch(u){if(Pp(u))return;throw u}s=!1,n=void 0}}async streamMessages(e,t){let r=new AbortController,o=()=>r.abort();if(this.transport)return{uiMessageStream:await this.transport.sendMessages({trigger:"submit-message",chatId:this.chatId,messageId:void 0,messages:e,abortSignal:r.signal}),message:ga(e),abort:o};let n=this.agent,a=await n.stream({prompt:await co(e,{tools:n.tools}),abortSignal:r.signal,options:void 0,experimental_sandbox:this.sandbox});return{uiMessageStream:$x(a.fullStream,t,e),message:ga(e),abort:o}}};function Ex(e){return e.tools===void 0&&e.reasoning===void 0&&e.responseStatistics===void 0&&e.contextSize===void 0?new ha:new ha({tools:e.tools,reasoning:e.reasoning,responseStatistics:e.responseStatistics,contextSize:e.contextSize})}function kx(e){if(e.renderer)return e.renderer;if(!e.screen&&!e.userInput)return;return new ha({tools:e.tools,reasoning:e.reasoning,responseStatistics:e.responseStatistics,contextSize:e.contextSize,input:e.userInput,output:e.screen})}async function*$x(e,t,r=[]){var o,n;let a=new Set,s=new Set,i=new Set,u,c,d=!1;yield{type:"start",messageId:(n=(o=ga(r))==null?void 0:o.id)!=null?n:t()};for await(let p of e)switch(p.type){case"text-start":a.add(p.id),yield{type:"text-start",id:p.id,providerMetadata:p.providerMetadata};break;case"text-delta":if(!a.has(p.id))a.add(p.id),yield{type:"text-start",id:p.id,providerMetadata:p.providerMetadata};yield{type:"text-delta",id:p.id,delta:p.text,providerMetadata:p.providerMetadata};break;case"text-end":a.delete(p.id),yield{type:"text-end",id:p.id,providerMetadata:p.providerMetadata};break;case"reasoning-start":s.add(p.id),yield{type:"reasoning-start",id:p.id,providerMetadata:p.providerMetadata};break;case"reasoning-delta":if(!s.has(p.id))s.add(p.id),yield{type:"reasoning-start",id:p.id,providerMetadata:p.providerMetadata};yield{type:"reasoning-delta",id:p.id,delta:p.text,providerMetadata:p.providerMetadata};break;case"reasoning-end":s.delete(p.id),yield{type:"reasoning-end",id:p.id,providerMetadata:p.providerMetadata};break;case"tool-input-start":yield{type:"tool-input-start",toolCallId:p.id,toolName:p.toolName,providerExecuted:p.providerExecuted,providerMetadata:p.providerMetadata,toolMetadata:p.toolMetadata,dynamic:p.dynamic,title:p.title};break;case"tool-input-delta":yield{type:"tool-input-delta",toolCallId:p.id,inputTextDelta:p.delta};break;case"tool-call":i.add(p.toolCallId),yield{type:"tool-input-available",toolCallId:p.toolCallId,toolName:p.toolName,input:p.input,providerExecuted:p.providerExecuted,providerMetadata:p.providerMetadata,toolMetadata:p.toolMetadata,dynamic:p.dynamic,title:p.title};break;case"tool-approval-request":if(!i.has(p.toolCall.toolCallId))i.add(p.toolCall.toolCallId),yield{type:"tool-input-available",toolCallId:p.toolCall.toolCallId,toolName:p.toolCall.toolName,input:p.toolCall.input,providerExecuted:p.toolCall.providerExecuted,providerMetadata:p.toolCall.providerMetadata,toolMetadata:p.toolCall.toolMetadata,dynamic:p.toolCall.dynamic,title:p.toolCall.title};yield{type:"tool-approval-request",approvalId:p.approvalId,toolCallId:p.toolCall.toolCallId,isAutomatic:p.isAutomatic};break;case"tool-approval-response":yield{type:"tool-approval-response",approvalId:p.approvalId,approved:p.approved,reason:p.reason,providerExecuted:p.providerExecuted};break;case"tool-result":yield{type:"tool-output-available",toolCallId:p.toolCallId,output:p.output,providerExecuted:p.providerExecuted,providerMetadata:p.providerMetadata,toolMetadata:p.toolMetadata,dynamic:p.dynamic,preliminary:p.preliminary};break;case"tool-error":yield{type:"tool-output-error",toolCallId:p.toolCallId,errorText:Cp(p.error),providerExecuted:p.providerExecuted,providerMetadata:p.providerMetadata,toolMetadata:p.toolMetadata,dynamic:p.dynamic};break;case"tool-output-denied":yield{type:"tool-output-denied",toolCallId:p.toolCallId};break;case"source":if(p.sourceType==="url")yield{type:"source-url",sourceId:p.id,url:p.url,title:p.title,providerMetadata:p.providerMetadata};else yield{type:"source-document",sourceId:p.id,mediaType:p.mediaType,title:p.title,filename:p.filename,providerMetadata:p.providerMetadata};break;case"file":yield{type:"file",url:Op(p.file.mediaType,p.file.base64),mediaType:p.file.mediaType,providerMetadata:p.providerMetadata};break;case"reasoning-file":yield{type:"reasoning-file",url:Op(p.file.mediaType,p.file.base64),mediaType:p.file.mediaType,providerMetadata:p.providerMetadata};break;case"start-step":yield{type:"start-step"};break;case"finish-step":u=p.usage,c=p.performance,yield{type:"finish-step"};break;case"finish":yield*Rp(a,s),d=!0,yield{type:"finish",finishReason:p.finishReason,messageMetadata:Mx(u!=null?u:p.totalUsage,c)};break;case"abort":yield{type:"abort",reason:p.reason};break;case"error":yield{type:"error",errorText:Cp(p.error)};break}if(!d)yield*Rp(a,s),yield{type:"finish"}}function Mx(e,t){if((e==null?void 0:e.totalTokens)==null&&(e==null?void 0:e.outputTokens)==null&&(t==null?void 0:t.outputTokensPerSecond)==null)return;return{...(e==null?void 0:e.totalTokens)==null&&(e==null?void 0:e.outputTokens)==null?{}:{usage:{...e.totalTokens==null?{}:{totalTokens:e.totalTokens},...e.outputTokens==null?{}:{outputTokens:e.outputTokens}}},...(t==null?void 0:t.outputTokensPerSecond)==null?{}:{performance:{outputTokensPerSecond:t.outputTokensPerSecond}}}}function*Rp(e,t){for(let r of e)yield{type:"text-end",id:r};e.clear();for(let r of t)yield{type:"reasoning-end",id:r};t.clear()}function Rx(e,t){return{id:e,role:"user",parts:[{type:"text",text:t}]}}function Ap(e,t,r){var o;if(r&&((o=e.at(-1))==null?void 0:o.role)==="assistant"){e[e.length-1]=t;return}e.push(t)}function ga(e){let t=e.at(-1);return(t==null?void 0:t.role)==="assistant"?t:void 0}function Ax(e){let t=[];for(let[r,o]of e.parts.entries()){if(!ie(o)||o.state!=="approval-requested"||o.approval.isAutomatic===!0)continue;t.push({approvalId:o.approval.id,toolCallId:o.toolCallId,toolName:He(o),title:o.title,input:o.input,providerExecuted:o.providerExecuted,messageId:e.id,partIndex:r})}return t}function Cx(e,t,r){let o=e.parts[t.partIndex];if(!o||!ie(o)||o.toolCallId!==t.toolCallId)throw Error(`Could not find tool approval request ${t.approvalId}.`);o.state="approval-responded",o.approval={id:t.approvalId,approved:r.approved,...r.reason?{reason:r.reason}:{}}}function Cp(e){if(e instanceof Error)return e.message;if(typeof e==="string")return e;return JSON.stringify(e)}function Op(e,t){return`data:${e};base64,${t}`}function Pp(e){return e instanceof Error&&e.message==="Interrupted"}async function Yp(e){await new Ix(e).run()}async function Xp(e){if(e.prompt!==void 0)Ox(e.prompt);await Yp({title:`broods · ${e.agent.name}`,tools:"full",transport:new ef(e.client,e.agent)})}async function Qp(e){let t=hp({stream:tf(e.client.stream(e.agent,{input:e.prompt}),void 0,()=>{})});for await(let r of t)process.stdout.write(r);process.stdout.write(`
|
|
154
|
-
`)}async function Ox(e){let t=process.stdin.listenerCount("data"),r=Date.now()+1e4;while(process.stdin.listenerCount("data")<=t){if(Date.now()>r)return;await new Promise((o)=>setTimeout(o,20))}process.stdin.emit("data",Buffer.from(e)),process.stdin.emit("data",Buffer.from("\r"))}class ef{client;agent;conversationKey=`tui-${Pt()}`;sentApprovals=new Set;sentUserTurns=0;constructor(e,t){this.client=e;this.agent=t}async reconnectToStream(){return null}async sendMessages(e){let t=this.pendingEvents(await co(e.messages));if(t.events.length===0)throw Error("Nothing new to send: the agent already saw this turn.");let r=this.client.stream(this.agent,{conversationKey:this.conversationKey,events:t.events});return wp({stream:tf(r,e.abortSignal,t.commit),originalMessages:e.messages,generateMessageId:Pt,sendSources:!0})}pendingEvents(e){let t=[],r=[],o=0;for(let n of e){if(n.role==="user"){if(o+=1,o>this.sentUserTurns)t.push(n);continue}if(n.role!=="tool")continue;for(let a of n.content)if(a.type==="tool-approval-response"&&!this.sentApprovals.has(a.approvalId))r.push(a)}if(r.length>0)t.push({role:"tool",content:r});return{events:t,commit:()=>{this.sentUserTurns=o;for(let n of r)this.sentApprovals.add(n.approvalId)}}}}function tf(e,t,r){let o=!1,n=()=>void e.return(void 0);return new ReadableStream({pull:async function(a){let s=await Promise.race([e.next(),Px(t)]);if(t?.aborted){n(),a.close();return}if(!o)o=!0,r();if(s.done)a.close();else a.enqueue(s.value)},cancel:n})}function Px(e){return new Promise((t)=>{if(!e)return;let r=()=>t({done:!0,value:void 0});if(e.aborted)r();else e.addEventListener("abort",r,{once:!0})})}var rf={name:"broods",version:"0.
|
|
154
|
+
`)}async function Ox(e){let t=process.stdin.listenerCount("data"),r=Date.now()+1e4;while(process.stdin.listenerCount("data")<=t){if(Date.now()>r)return;await new Promise((o)=>setTimeout(o,20))}process.stdin.emit("data",Buffer.from(e)),process.stdin.emit("data",Buffer.from("\r"))}class ef{client;agent;conversationKey=`tui-${Pt()}`;sentApprovals=new Set;sentUserTurns=0;constructor(e,t){this.client=e;this.agent=t}async reconnectToStream(){return null}async sendMessages(e){let t=this.pendingEvents(await co(e.messages));if(t.events.length===0)throw Error("Nothing new to send: the agent already saw this turn.");let r=this.client.stream(this.agent,{conversationKey:this.conversationKey,events:t.events});return wp({stream:tf(r,e.abortSignal,t.commit),originalMessages:e.messages,generateMessageId:Pt,sendSources:!0})}pendingEvents(e){let t=[],r=[],o=0;for(let n of e){if(n.role==="user"){if(o+=1,o>this.sentUserTurns)t.push(n);continue}if(n.role!=="tool")continue;for(let a of n.content)if(a.type==="tool-approval-response"&&!this.sentApprovals.has(a.approvalId))r.push(a)}if(r.length>0)t.push({role:"tool",content:r});return{events:t,commit:()=>{this.sentUserTurns=o;for(let n of r)this.sentApprovals.add(n.approvalId)}}}}function tf(e,t,r){let o=!1,n=()=>void e.return(void 0);return new ReadableStream({pull:async function(a){let s=await Promise.race([e.next(),Px(t)]);if(t?.aborted){n(),a.close();return}if(!o)o=!0,r();if(s.done)a.close();else a.enqueue(s.value)},cancel:n})}function Px(e){return new Promise((t)=>{if(!e)return;let r=()=>t({done:!0,value:void 0});if(e.aborted)r();else e.addEventListener("abort",r,{once:!0})})}var rf={name:"broods",version:"0.12.0",description:"CLI + TypeScript SDK for the broods agent platform.",type:"module",license:"MIT",homepage:"https://github.com/beeblastco/broods#readme",repository:{type:"git",url:"git+https://github.com/beeblastco/broods.git",directory:"packages/broods"},bugs:{url:"https://github.com/beeblastco/broods/issues"},keywords:["agents","ai","sdk","cli","broods"],bin:{broods:"dist/cli/index.js"},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./account":{types:"./dist/account.d.ts",import:"./dist/account.js"}},main:"./dist/index.js",types:"./dist/index.d.ts",files:["dist","README.md","LICENSE.md"],scripts:{build:"bun scripts/build.ts && rollup -c rollup.dts.config.mjs && bun scripts/clean-dts-side-effects.ts && rm -rf .dts-temp",check:"tsc --noEmit","pack:check":"bun run build && npm pack --dry-run",test:"bun test"},engines:{node:">=22"},dependencies:{esbuild:"^0.28.2"},peerDependencies:{ai:"^7.0.58"},devDependencies:{"@ai-sdk/tui":"^1.0.59",ai:"^7.0.58","@chat-adapter/discord":"^4.35.0","@chat-adapter/github":"^4.35.0","@chat-adapter/slack":"^4.35.0","@chat-adapter/telegram":"^4.35.0","@types/bun":"^1.3.14",rollup:"^4.62.2",typescript:"^6.0.3","rollup-plugin-dts":"^6.4.1"}};var Aa=rf.version,ot="https://dashboard.broods.app",Wt="eu-west-1",Bx=[{region:"eu-west-1",label:"eu-west-1 (Ireland)"},{region:"us-east-1",label:"us-east-1 (US East)"},{region:"ap-southeast-1",label:"ap-southeast-1 (Singapore)"}],ge=`Global options:
|
|
155
155
|
--project <name> Project name override (default: package name or folder)
|
|
156
156
|
--stage <name> Target stage override (BROODS_STAGE otherwise)
|
|
157
157
|
--base-url <url> broods API base URL for sync/env calls (default: discovered at login)
|
package/dist/index.d.ts
CHANGED
|
@@ -82,6 +82,7 @@ interface AgentConfig {
|
|
|
82
82
|
denyTools?: string[];
|
|
83
83
|
skills?: AgentSkillsConfig;
|
|
84
84
|
subagent?: AgentSubagentConfig;
|
|
85
|
+
scheduler?: AgentSchedulerConfig;
|
|
85
86
|
policy?: AgentPolicyConfig;
|
|
86
87
|
publicAccess?: boolean;
|
|
87
88
|
[key: string]: unknown;
|
|
@@ -112,6 +113,14 @@ interface AgentSkillsConfig {
|
|
|
112
113
|
allowed?: string[];
|
|
113
114
|
[key: string]: unknown;
|
|
114
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Opt-in for the `schedule` tool. Off by default: a scheduled task starts
|
|
118
|
+
* billable agent runs long after the turn that asked for it.
|
|
119
|
+
*/
|
|
120
|
+
interface AgentSchedulerConfig {
|
|
121
|
+
enabled?: boolean;
|
|
122
|
+
[key: string]: unknown;
|
|
123
|
+
}
|
|
115
124
|
interface AgentSubagentConfig {
|
|
116
125
|
enabled?: boolean;
|
|
117
126
|
allowed?: string[];
|
|
@@ -474,6 +483,7 @@ interface WorkspaceConfig {
|
|
|
474
483
|
interface TelegramSource {
|
|
475
484
|
chatId: number;
|
|
476
485
|
messageId: string;
|
|
486
|
+
messageThreadId?: number;
|
|
477
487
|
threadId: string;
|
|
478
488
|
fromUserId?: number;
|
|
479
489
|
fromUsername?: string;
|
|
@@ -1913,7 +1923,7 @@ interface ProviderSettingsInput {
|
|
|
1913
1923
|
}
|
|
1914
1924
|
/** Per-provider settings; provider names stay synced with core's `AgentConfig`. */
|
|
1915
1925
|
type ProviderConfigInput = Partial<Record<keyof NonNullable<AgentConfig["provider"]>, ProviderSettingsInput>>;
|
|
1916
|
-
type AgentDefinitionConfig = EnvRefString<Pick<AgentConfig, "agent" | "model" | "session" | "tools">> & {
|
|
1926
|
+
type AgentDefinitionConfig = EnvRefString<Pick<AgentConfig, "agent" | "model" | "scheduler" | "session" | "tools">> & {
|
|
1917
1927
|
provider?: ProviderConfigInput;
|
|
1918
1928
|
} & {
|
|
1919
1929
|
harness?: HarnessDefinition;
|