broods 0.37.1 → 0.38.1
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 +28 -0
- package/dist/{chunk-tgqhxn4k.js → chunk-9ex5d29v.js} +4 -4
- package/dist/{chunk-1vpr1s8y.js → chunk-rk1v0qm8.js} +1 -1
- package/dist/cli/index.js +6 -4
- package/dist/index.d.ts +70 -5
- package/dist/index.js +1 -1
- package/package.json +4 -4
- /package/dist/{chunk-z0awwr22.js → chunk-f294wr3z.js} +0 -0
package/dist/account.d.ts
CHANGED
|
@@ -351,6 +351,7 @@ interface AgentChannelsConfig {
|
|
|
351
351
|
discord?: AgentDiscordChannelConfig;
|
|
352
352
|
pancake?: AgentPancakeChannelConfig;
|
|
353
353
|
zalo?: AgentZaloChannelConfig;
|
|
354
|
+
matrix?: AgentMatrixChannelConfig;
|
|
354
355
|
[key: string]: unknown;
|
|
355
356
|
}
|
|
356
357
|
/**
|
|
@@ -426,6 +427,33 @@ interface AgentDiscordChannelConfig {
|
|
|
426
427
|
partition?: ChannelPartition;
|
|
427
428
|
[key: string]: unknown;
|
|
428
429
|
}
|
|
430
|
+
/**
|
|
431
|
+
* A Matrix account the agent speaks as. Matrix has no bot concept, so this is
|
|
432
|
+
* usually a person's own account: replies carry a per-message profile named
|
|
433
|
+
* `botName`, and `mentionText` decides what addresses the agent, because a
|
|
434
|
+
* mention of the account would also be a mention of its owner.
|
|
435
|
+
*/
|
|
436
|
+
interface AgentMatrixChannelConfig {
|
|
437
|
+
id?: string;
|
|
438
|
+
/** Homeserver base URL, e.g. `https://matrix.org`. */
|
|
439
|
+
apiUrl?: string;
|
|
440
|
+
/** Access token of the account; `apps/matrix-forwarder` syncs with it. */
|
|
441
|
+
botToken?: string;
|
|
442
|
+
/** Room ids. */
|
|
443
|
+
allowedChannelIds?: string[];
|
|
444
|
+
/** Matrix user ids, e.g. `@alice:matrix.org`. */
|
|
445
|
+
allowedUserIds?: string[];
|
|
446
|
+
/** Name replies are shown under. Unset, replies look like the account's own messages. */
|
|
447
|
+
botName?: string;
|
|
448
|
+
/**
|
|
449
|
+
* Text that addresses the agent, e.g. `@georgi-ai`. Unset, a mention of the
|
|
450
|
+
* account does. Other messages are stored as context either way.
|
|
451
|
+
*/
|
|
452
|
+
mentionText?: string;
|
|
453
|
+
trace?: "enabled" | "disabled";
|
|
454
|
+
partition?: ChannelPartition;
|
|
455
|
+
[key: string]: unknown;
|
|
456
|
+
}
|
|
429
457
|
interface AgentPancakeChannelConfig {
|
|
430
458
|
allowedChannelIds?: string[];
|
|
431
459
|
allowedUserIds?: string[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
function B(e){if(e.events&&e.input!==void 0)throw Error("Run input accepts either `input` or `events`, not both");if(e.events&&e.events.length>0)return e.events;if(typeof e.input==="string")return[{role:"user",content:[{type:"text",text:e.input}]}];throw Error("Run input requires `input` (string) or a non-empty `events` array")}async function*me(e){let n=e.getReader(),t=new TextDecoder,o="";try{while(!0){let{done:r,value:s}=await n.read();if(r)break;o+=t.decode(s,{stream:!0});let i=o.split(`
|
|
2
|
-
`);o=i.pop()??"";for(let a of i)if(a.startsWith("data: "))yield a.slice(6)}}finally{n.releaseLock()}}var xe=500,ge=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,le=/^(?!0{32}$)[0-9a-f]{32}$/;function Ce(e){return e==="DEBUG"||e==="INFO"||e==="WARN"||e==="ERROR"}function Oe(e){if(typeof e!=="object"||e===null)return!1;let n=e;if(n.type==="subscribe")return de(n);if(n.type==="unsubscribe")return
|
|
3
|
-
`,"utf8")}function _(){return process.env.BROODS_STAGE}function f(e){let n=e.length;while(n>0&&e.charCodeAt(n-1)===47)n-=1;return e.slice(0,n)}function te(e){try{let n=new URL(e);if(!n.hostname.startsWith(`${
|
|
4
|
-
`).replace(/\\"/g,'"');if(e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);let n=e.indexOf(" #");return n>=0?e.slice(0,n).trimEnd():e}function Te(){try{let e=JSON.parse(D(C,"utf8"));if(typeof e.baseUrl!=="string"||typeof e.token!=="string")return null;return{baseUrl:f(e.baseUrl),...typeof e.dashboardUrl==="string"?{dashboardUrl:f(e.dashboardUrl)}:{},token:e.token}}catch{return null}}var z="https://gateway.broods.app";class he extends Error{accepted;constructor(e){super(`Ingress ${e.eventId} was accepted asynchronously with status ${e.status??"queued"}`);this.accepted=e;this.name="IngressAcceptedError"}}class j{baseUrl;apiKey;fetchImpl;constructor(e={}){h(),this.baseUrl=V(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||z),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||void 0,this.fetchImpl=e.fetch??fetch}channelWebhookUrl(e){return`${this.baseUrl}${e.webhookPath.startsWith("/")?"":"/"}${e.webhookPath}`}accountWebhookUrl(e,n){let t=[e,n].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${t.join("/")}`}stageWebhookUrl(e,n,t){let o=[e,"dev",n,t].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${o.join("/")}`}agent(e,n){if(typeof e==="string"){let o=e,r=n??"";if(!r)throw Error(`Agent ${o} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:r,run:(s)=>this.run({...s,agentName:o,agentId:r}),runAsync:(s)=>this.runAsync({...s,agentName:o,agentId:r}),continue:(s)=>this.continue({...s,agentId:r}),stream:(s)=>this.stream({...s,agentName:o,agentId:r})}}let t=e;if(!t.id)throw Error(`Agent ${t.name} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:t.id,run:(o)=>this.run(t,o),runAsync:(o)=>this.runAsync(t,o),continue:(o)=>this.continue(t,o),stream:(o)=>this.stream(t,o)}}async run(e,n){let t=[],o="",r=n?this.stream(e,n):this.stream(e);for await(let s of r)if(t.push(s),s.type==="text-delta")o+=s.text;return{text:o,events:t}}async*stream(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o=q(t,"cli"),r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`,s=await this.openStream(o,r);if(!s.ok)throw Error(`Run failed: ${s.status} ${await s.text()}`);if(s.status===202)throw new he(J(await s.json(),o));if(!s.body)throw Error("Run response has no body");for await(let i of me(s.body)){let a;try{a=JSON.parse(i)}catch{continue}if(a.type==="error")throw Error(`Agent run failed: ${$e(a.error)}`);yield a}}async runAsync(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o={...q(t,"async"),background:!0},r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(r,o,"Async run")}async continue(e,n){let t=n?e:null,o=n??e,r={agentId:t?t.id:e.agentId,eventId:o.eventId??`continue-${crypto.randomUUID()}`,conversationKey:o.conversationKey,continue:!0},s=t?this.scopedUrl(t):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(s,r,"Continue")}async getAsyncStatus(e){let n=this.resolveStatusUrl(e),t=await this.fetchJson(n,{method:"GET",headers:this.apiKeyHeaders()});if(t.status===404)return{status:"not_found"};if(!t.ok)throw Error(`Status check failed: ${t.status} ${await t.text()}`);return await t.json()}async waitForAsyncStatus(e,n={}){let t=Date.now()+(n.timeoutMs??180000),o=n.intervalMs??2000;while(Date.now()<t){if(n.signal?.aborted)throw Error("Async status polling aborted.");let r=await this.getAsyncStatus(e);if(r.status==="awaiting_approval"||r.status==="awaiting_input"||r.status==="completed"||r.status==="failed"||r.status==="expired"||r.status==="not_found")return r;await tn(o,n.signal)}throw Error("Polling timeout")}async createCron(e){let n=await this.fetchJson(`${this.baseUrl}/v1/crons`,{method:"POST",headers:this.apiKeyHeaders(),body:JSON.stringify(en(e))});if(n.status!==201)throw Error(`Create cron job failed: ${n.status} ${await n.text()}`);return await n.json()}async listCrons(){let e=await this.fetchJson(`${this.baseUrl}/v1/crons`,{method:"GET",headers:this.apiKeyHeaders()});if(!e.ok)throw Error(`List cron jobs failed: ${e.status} ${await e.text()}`);return(await e.json()).crons}async getCron(e){let n=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}`,{method:"GET",headers:this.apiKeyHeaders()});if(n.status===404)return null;if(!n.ok)throw Error(`Get cron job failed: ${n.status} ${await n.text()}`);return await n.json()}async listCronRuns(e,n={}){let t=new URLSearchParams;if(n.limit!==void 0)t.set("limit",String(n.limit));let o=t.size>0?`?${t}`:"",r=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}/runs${o}`,{method:"GET",headers:this.apiKeyHeaders()});if(!r.ok)throw Error(`List cron job runs failed: ${r.status} ${await r.text()}`);return(await r.json()).runs}async updateCron(e,n){let t=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}`,{method:"PATCH",headers:this.apiKeyHeaders(),body:JSON.stringify(n)});if(!t.ok)throw Error(`Update cron job failed: ${t.status} ${await t.text()}`);return await t.json()}async deleteCron(e){let n=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}`,{method:"DELETE",headers:this.apiKeyHeaders()});if(n.status===404)return!1;if(!n.ok)throw Error(`Delete cron job failed: ${n.status} ${await n.text()}`);return(await n.json()).deleted}scopedUrl(e){if(e.projectSlug&&e.stageSlug&&e.endpointId)return`${this.baseUrl}/v1/projects/${encodeURIComponent(e.projectSlug)}/stages/${encodeURIComponent(e.stageSlug)}/agents/${encodeURIComponent(e.endpointId)}`;return`${this.baseUrl}/v1/runs`}asyncAgentRun(e,n){return{...e,conversationKey:n,poll:()=>this.getAsyncStatus(e),wait:(t)=>this.waitForAsyncStatus(e,t)}}async postAcceptedRun(e,n,t){let o=await this.fetchJson(e,{method:"POST",headers:this.apiKeyHeaders(),body:JSON.stringify(n)});if(o.status!==202)throw Error(`${t} failed: ${o.status} ${await nn(o,"202 JSON")}`);return this.asyncAgentRun(J(await o.json(),n),n.conversationKey)}async openStream(e,n){if(this.apiKey)return await this.fetchCore(e,n,{Authorization:`Bearer ${this.apiKey}`});throw Error(`BroodsClient streams directly from the core service at ${this.baseUrl}. Provide apiKey. For a self-hosted core service, set host/baseUrl or BROODS_HOST/BROODS_BASE_URL.`)}async fetchCore(e,n,t){try{return await this.fetchImpl(n,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t},body:JSON.stringify(e)})}catch(o){throw Error(`Cannot access the broods core service at ${n}. The SDK uses ${z} by default; set host/baseUrl or BROODS_HOST/BROODS_BASE_URL to your own core service URL if your account uses a custom deployment. Cause: ${o instanceof Error?o.message:String(o)}`)}}apiKeyHeaders(){if(!this.apiKey)throw Error("BroodsClient requires apiKey or BROODS_API_KEY.");return{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`}}async fetchJson(e,n){try{return await this.fetchImpl(e,{...n,headers:{"Content-Type":"application/json",...n.headers}})}catch(t){throw Error(`Cannot access the broods core service at ${e}. Cause: ${t instanceof Error?t.message:String(t)}`)}}resolveStatusUrl(e){if(typeof e!=="string")return e.statusUrl;if(/^https?:\/\//.test(e))return e;return on(this.baseUrl,e)}}function V(e){let n=e.trim(),t=/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(n)?n:`https://${n}`;return f(t)}function q(e,n){let t=e.eventId??`${n}-${Date.now()}`;return{agentId:e.agentId,eventId:t,conversationKey:e.conversationKey??t,events:B(e),...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}}function $e(e){if(typeof e==="string")return e;if(!e||typeof e!=="object")return String(e);let n=e,t=n.data?.error?.message??n.message??n.responseBody??JSON.stringify(e),o=n.name?`${n.name}: `:"",r=n.statusCode?` (HTTP ${n.statusCode})`:"";return`${o}${t}${r}`}function J(e,n){if(!e||typeof e!=="object")throw Error("Async response must be an object");let t=e.statusUrl;if(typeof t!=="string"||t.length===0)throw Error("Async response missing statusUrl");let o=typeof e.runId==="string"?e.runId:_e(t);if(!o)throw Error("Async response missing runId");let r=typeof e.eventId==="string"?e.eventId:o,{status:s,requestedMode:i}=e;return{statusUrl:t,runId:o,eventId:r,agentId:n.agentId,...s==="accepted"||s==="queued"||s==="applied"||s==="processing"?{status:s}:{},...i==="reject"||i==="followup"||i==="collect"||i==="steer"?{requestedMode:i}:{}}}function _e(e){let n=new URL(e).pathname.match(/\/v1\/runs\/([^/]+)$/);return n?.[1]?decodeURIComponent(n[1]):void 0}function en(e){if("agentId"in e)return e;let n=e.agent,t=typeof n==="string"?n:n.id,{agent:o,...r}=e;return{...r,agentId:t}}async function nn(e,n){if((e.headers.get("content-type")??"").toLowerCase().includes("text/event-stream"))return await e.body?.cancel().catch(()=>{}),`expected ${n}, but the server returned an SSE stream. This usually means the core deployment ignored the background flag and ran the request on the direct streaming runner.`;let o=await e.text();if(o.length<=2000)return o;return`${o.slice(0,2000)}... [truncated ${o.length-2000} chars]`}function tn(e,n){return new Promise((t,o)=>{if(n?.aborted){o(Error("Async status polling aborted."));return}let r=setTimeout(t,e);n?.addEventListener("abort",()=>{clearTimeout(r),o(Error("Async status polling aborted."))},{once:!0})})}function on(e,n){return`${V(e)}/v1/runs/${encodeURIComponent(n)}`}var rn=2000,Y=0,b=1;class Pe{baseUrl;apiKey;WebSocketImpl;connectTimeoutMs;constructor(e={}){if(h(),this.baseUrl=re(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||z),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||"",!this.apiKey)throw Error("BroodsWebSocketClient requires apiKey or BROODS_API_KEY.");this.WebSocketImpl=e.WebSocket,this.connectTimeoutMs=e.connectTimeoutMs??rn}subscribe(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=sn(e),s=oe(this.baseUrl),i=new t(o,E(this.apiKey)),a=!1,u=!1,l=setTimeout(()=>{if(!a)m(s)},this.connectTimeoutMs),A=(c=1000,I="client closed")=>{if(u)return;if(u=!0,clearTimeout(l),e.signal?.removeEventListener("abort",R),i.readyState===b||i.readyState===Y)i.close(c,I)},m=(c)=>{n.onError?.(c),A(1011,"websocket error")},ue=()=>{n.onDone?.(),A(1000,"done")},R=()=>{if(i.readyState===b)i.send(JSON.stringify({type:"cancel"}));m(Error("WebSocket run aborted."))};return e.signal?.addEventListener("abort",R,{once:!0}),i.onopen=()=>{if(a=!0,clearTimeout(l),e.signal?.aborted){R();return}i.send(JSON.stringify({type:"execute",agentId:r,...e.answers?{answers:e.answers}:{events:B(e)},sessionId:e.sessionId,...e.eventId!==void 0?{eventId:e.eventId}:{},...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}))},i.onmessage=(c)=>{if(typeof c.data!=="string")return;let I=Q(c.data);if(!I)return;let k=ee(I,n);switch(n.onMessage?.(k),k.type){case"meta":n.onMeta?.(k);break;case"done":ue();break;case"error":m(Error(X(k.error)));break}},i.onerror=()=>{m(s)},i.onclose=(c)=>{if(clearTimeout(l),e.signal?.removeEventListener("abort",R),u||c.code===1000)return;m(Error(c.reason||"WebSocket connection closed."))},{url:o,sendControl:function(c){if(i.readyState!==b)throw Error("WebSocket is not open");i.send(JSON.stringify({type:"control",...c}))},close:A}}attach(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=new t(o,E(this.apiKey)),s=!1,i=(a=1000,u="client closed")=>{if(s)return;if(s=!0,r.readyState===b||r.readyState===Y)r.close(a,u)};return r.onopen=()=>r.send(JSON.stringify({type:"attach",...e,signal:void 0,agent:void 0})),r.onmessage=(a)=>{if(typeof a.data!=="string")return;let u=Q(a.data);if(!u)return;let l=ee(u,n);if(n.onMessage?.(l),l.type==="done")n.onDone?.();if(l.type==="error")n.onError?.(Error(X(l.error)))},r.onerror=()=>n.onError?.(oe(this.baseUrl)),r.onclose=(a)=>{if(!s&&a.code!==1000)n.onError?.(Error(a.reason||"WebSocket connection closed."))},{url:o,sendControl:function(a){if(r.readyState!==b)throw Error("WebSocket is not open");r.send(JSON.stringify({type:"control",...a}))},close:i}}async*stream(e){let n=[],t=!1,o=null,r=null,s=()=>{r?.(),r=null},i=this.subscribe(e,{onMessage:function(a){n.push(a),s()},onDone:function(){t=!0,s()},onError:function(a){o=a,s()}});try{while(!0){if(n.length>0){yield n.shift();continue}if(o)throw o;if(t)return;await new Promise((a)=>{r=a})}}finally{i.close()}}buildUrl(e){let n=an(e),t=e.projectSlug??e.agent?.projectSlug,o=e.stageSlug??e.agent?.stageSlug,r=t&&o?`/projects/${encodeURIComponent(t)}/stages/${encodeURIComponent(o)}`:"";return`${K(this.baseUrl)}/v1${r}/agents/${encodeURIComponent(n)}/ws`}resolveWebSocket(){let e=this.WebSocketImpl??globalThis.WebSocket;if(!e)throw Error("WebSocket is not available. Pass a WebSocket implementation in BroodsWebSocketClient options.");return e}}function K(e){let n=new URL(re(e));if(n.protocol==="https:")n.protocol="wss:";if(n.protocol==="http:")n.protocol="ws:";return f(n.toString())}function E(e){return["broods.v1",`broods.token.${e}`]}function X(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&typeof e.message==="string")return e.message;return e===void 0?"WebSocket stream error.":JSON.stringify(e)}function re(e){let n=e.trim();if(/^wss?:\/\//.test(n))return f(n);return V(n)}function Q(e){try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}function sn(e){let n=e.agentId??e.agent?.id??e.endpointId;if(!n)throw Error("WebSocket run requires agent, agentId, or endpointId.");return n}function an(e){let n=e.endpointId??e.agent?.endpointId??e.agent?.id;if(!n)throw Error("WebSocket run requires agent or endpointId.");return n}function ee(e,n){if(e.type!=="output")return e;let t=e;return n.onOutput?.(t),t.data}function oe(e){return Error(`Cannot access the WebSocket service at ${e}.`)}var ie=Symbol.for("broods.resource"),ae=Symbol.for("broods.config"),ce=Symbol.for("broods.connection"),se=/^[A-Z][A-Z0-9_]{0,63}$/,Me=new Proxy((e)=>{if(!se.test(e))throw Error("env name must match /^[A-Z][A-Z0-9_]*$/ and be at most 64 characters.");return{__beeblastEnv:!0,name:e}},{get:function(e,n,t){if(typeof n==="string"&&se.test(n))throw Error(`env.${n} is not supported; use env("${n}")`);return Reflect.get(e,n,t)}});function Ne(e){let{name:n,description:t,...o}=e;return d("agent",n,t,o)}function je(e){return{[ae]:!0,config:e}}function qe(e){let{name:n,description:t,...o}=e;return d("cron",n,t,o)}function Le(e){return e}function De(e){let{name:n,description:t,...o}=e;return d("mcp",n,t,o)}function Ue(e){let{name:n,description:t,...o}=e;return d("policy",n,t,o)}function Be(e){let{name:n,description:t,...o}=e;return d("sandbox",n,t,o)}function Fe(e){let{name:n,description:t,...o}=e;return d("skill",n,t,o)}function Ze(e){let{name:n,description:t,...o}=e;return d("workspace",n,t,o)}function He(e){return y("discord",e)}function Ve(e){return y("github",e)}function Ke(e){return y("pancake",e)}function We(e){return y("slack",e)}function Ge(e){return y("telegram",e)}function Je(e){return y("zalo",e)}function Ye(e){let{name:n,description:t,channelId:o,guildId:r,...s}=e;return p(n,t,o,r,s)}function Xe(e){let{name:n,description:t,repo:o,...r}=e,[s,...i]=o.split("/");if(!s||i.length!==1||!i[0])throw Error(`Channel "${n}" repo must be "owner/name", not "${o}"`);return p(n,t,o,s,r)}function Qe(e){let{name:n,description:t,conversationId:o,...r}=e;return p(n,t,o,void 0,r)}function et(e){let{name:n,description:t,channelId:o,teamId:r,...s}=e;return p(n,t,o,r,s)}function tt(e){let{name:n,description:t,chatId:o,...r}=e;return p(n,t,o,void 0,r)}function nt(e){let{name:n,description:t,chatId:o,...r}=e;return p(n,t,o,void 0,r)}function ne(e){return Boolean(e&&typeof e==="object"&&e[ae])}function w(e){return Boolean(e&&typeof e==="object"&&e[ce])}function g(e){return Boolean(e&&typeof e==="object"&&e[ie])}function p(e,n,t,o,r){return d("channelRecord",e,n,{...r,externalId:t,...o?{workspaceRef:o}:{}})}function y(e,n){let{partition:t,...o}=n;return{[ce]:!0,kind:"connection",type:e,...t?{partition:t}:{},config:o}}function d(e,n,t,o){return{[ie]:!0,kind:e,name:n,...t?{description:t}:{},config:o}}
|
|
5
|
-
export{B,me,xe,Ce,Oe,Ae,F,ze,S,v,C,Z,H,_,f,te,h,O,z,he,j,V,Pe,K,E,Me,Ne,je,qe,Le,De,Ue,Be,Fe,Ze,He,Ve,Ke,We,Ge,Je,Ye,Xe,Qe,et,tt,nt,ne,w,g};
|
|
2
|
+
`);o=i.pop()??"";for(let a of i)if(a.startsWith("data: "))yield a.slice(6)}}finally{n.releaseLock()}}var xe=500,ge=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,le=/^(?!0{32}$)[0-9a-f]{32}$/;function Ce(e){return e==="DEBUG"||e==="INFO"||e==="WARN"||e==="ERROR"}function Oe(e){if(typeof e!=="object"||e===null)return!1;let n=e;if(n.type==="subscribe")return de(n);if(n.type==="unsubscribe")return M(n.stream);if(n.type==="fetchTrace")return ze(n.traceId);return!1}function Ae(e){return e==="task"||e==="cron"||e==="subtask"}function F(e){return typeof e==="string"&&ge.test(e)}function ze(e){return typeof e==="string"&&le.test(e)}function M(e){return e==="logs"||e==="traces"}function de(e){let n=e.stream;if(!M(n))return!1;let t=e.backfill;if(t!==void 0&&(typeof t!=="number"||!Number.isSafeInteger(t)||t<0||t>500))return!1;if(e.liveOnly!==void 0&&typeof e.liveOnly!=="boolean")return!1;let o=e.minLevel;if(o!==void 0&&!Ce(o))return!1;let r=e.sandboxId;return r===void 0||n==="logs"&&F(r)}import{mkdir as pe,readFile as fe,writeFile as ye}from"node:fs/promises";import{homedir as be}from"node:os";import{dirname as Re,join as Se}from"node:path";var S="broods",v="_generated",C=Se(be(),".broods","config.json"),N="broods.app",T="dashboard",Ie="gateway";async function Z(){let e=process.env.BROODS_TOKEN,n=process.env.BROODS_BASE_URL;if(e&&n)return{baseUrl:f(n),token:e,createdAt:new Date().toISOString()};try{let t=JSON.parse(await fe(C,"utf8"));if(typeof t.baseUrl!=="string"||!t.baseUrl)return null;return t}catch{return null}}async function H(e){await pe(Re(C),{recursive:!0}),await ye(C,`${JSON.stringify(e,null,2)}
|
|
3
|
+
`,"utf8")}function _(){return process.env.BROODS_STAGE}function f(e){let n=e.length;while(n>0&&e.charCodeAt(n-1)===47)n-=1;return e.slice(0,n)}function te(e){try{let n=new URL(e);if(!n.hostname.startsWith(`${T}.`))return;let t=n.hostname.slice(T.length+1);if(t!==N&&!t.endsWith(`.${N}`))return;return n.hostname=`${Ie}.${t}`,f(n.origin)}catch{return}}import{existsSync as P,readFileSync as D,statSync as ke}from"node:fs";import{join as W,resolve as L}from"node:path";var A=new Map,ve=new Set(Object.keys(process.env)),U=new Set;function h(e=process.cwd()){we(e);let n=Te();return{dashboardUrl:process.env.BROODS_DASHBOARD_URL??n?.dashboardUrl,baseUrl:process.env.BROODS_BASE_URL??n?.baseUrl,token:process.env.BROODS_TOKEN??n?.token,project:process.env.BROODS_PROJECT,stage:_()}}function O(e,n=process.cwd()){let t=process.env[e];if(t===void 0)return!1;let o=L(n);for(let r of[".env.local",".env"]){let s=W(o,r);if(!P(s))continue;let i=G(D(s,"utf8"));if(i[e]!==void 0)return i[e]!==t}return!0}function we(e){let n=L(e),t=process.env.BROODS_RELOAD_ENV==="1";for(let o of[".env",".env.local"]){let r=W(n,o);if(!P(r)){A.delete(r);continue}let s=ke(r).mtimeMs,i=A.get(r);if(i&&i.mtimeMs===s)continue;A.set(r,{mtimeMs:s});for(let[a,u]of Object.entries(G(D(r,"utf8"))))if(t||!ve.has(a)||U.has(a))process.env[a]=u,U.add(a)}}function G(e){let n={};for(let t of e.split(/\r?\n/)){let o=t.trim();if(!o||o.startsWith("#"))continue;let r=o.startsWith("export ")?o.slice(7).trim():o,s=r.indexOf("=");if(s<=0)continue;let i=r.slice(0,s).trim();if(!/^[A-Za-z_][A-Za-z0-9_]*$/.test(i))continue;n[i]=Ee(r.slice(s+1).trim())}return n}function Ee(e){if(e.startsWith('"')&&e.endsWith('"'))return e.slice(1,-1).replace(/\\n/g,`
|
|
4
|
+
`).replace(/\\"/g,'"');if(e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);let n=e.indexOf(" #");return n>=0?e.slice(0,n).trimEnd():e}function Te(){try{let e=JSON.parse(D(C,"utf8"));if(typeof e.baseUrl!=="string"||typeof e.token!=="string")return null;return{baseUrl:f(e.baseUrl),...typeof e.dashboardUrl==="string"?{dashboardUrl:f(e.dashboardUrl)}:{},token:e.token}}catch{return null}}var z="https://gateway.broods.app";class he extends Error{accepted;constructor(e){super(`Ingress ${e.eventId} was accepted asynchronously with status ${e.status??"queued"}`);this.accepted=e;this.name="IngressAcceptedError"}}class j{baseUrl;apiKey;fetchImpl;constructor(e={}){h(),this.baseUrl=V(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||z),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||void 0,this.fetchImpl=e.fetch??fetch}channelWebhookUrl(e){return`${this.baseUrl}${e.webhookPath.startsWith("/")?"":"/"}${e.webhookPath}`}accountWebhookUrl(e,n){let t=[e,n].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${t.join("/")}`}stageWebhookUrl(e,n,t){let o=[e,"dev",n,t].map(encodeURIComponent);return`${this.baseUrl}/v1/webhooks/${o.join("/")}`}agent(e,n){if(typeof e==="string"){let o=e,r=n??"";if(!r)throw Error(`Agent ${o} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:r,run:(s)=>this.run({...s,agentName:o,agentId:r}),runAsync:(s)=>this.runAsync({...s,agentName:o,agentId:r}),continue:(s)=>this.continue({...s,agentId:r}),stream:(s)=>this.stream({...s,agentName:o,agentId:r})}}let t=e;if(!t.id)throw Error(`Agent ${t.name} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:t.id,run:(o)=>this.run(t,o),runAsync:(o)=>this.runAsync(t,o),continue:(o)=>this.continue(t,o),stream:(o)=>this.stream(t,o)}}async run(e,n){let t=[],o="",r=n?this.stream(e,n):this.stream(e);for await(let s of r)if(t.push(s),s.type==="text-delta")o+=s.text;return{text:o,events:t}}async*stream(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o=q(t,"cli"),r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`,s=await this.openStream(o,r);if(!s.ok)throw Error(`Run failed: ${s.status} ${await s.text()}`);if(s.status===202)throw new he(J(await s.json(),o));if(!s.body)throw Error("Run response has no body");for await(let i of me(s.body)){let a;try{a=JSON.parse(i)}catch{continue}if(a.type==="error")throw Error(`Agent run failed: ${$e(a.error)}`);yield a}}async runAsync(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o={...q(t,"async"),background:!0},r=n?this.scopedUrl(e):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(r,o,"Async run")}async continue(e,n){let t=n?e:null,o=n??e,r={agentId:t?t.id:e.agentId,eventId:o.eventId??`continue-${crypto.randomUUID()}`,conversationKey:o.conversationKey,continue:!0},s=t?this.scopedUrl(t):`${this.baseUrl}/v1/runs`;return this.postAcceptedRun(s,r,"Continue")}async getAsyncStatus(e){let n=this.resolveStatusUrl(e),t=await this.fetchJson(n,{method:"GET",headers:this.apiKeyHeaders()});if(t.status===404)return{status:"not_found"};if(!t.ok)throw Error(`Status check failed: ${t.status} ${await t.text()}`);return await t.json()}async waitForAsyncStatus(e,n={}){let t=Date.now()+(n.timeoutMs??180000),o=n.intervalMs??2000;while(Date.now()<t){if(n.signal?.aborted)throw Error("Async status polling aborted.");let r=await this.getAsyncStatus(e);if(r.status==="awaiting_approval"||r.status==="awaiting_input"||r.status==="completed"||r.status==="failed"||r.status==="expired"||r.status==="not_found")return r;await tn(o,n.signal)}throw Error("Polling timeout")}async createCron(e){let n=await this.fetchJson(`${this.baseUrl}/v1/crons`,{method:"POST",headers:this.apiKeyHeaders(),body:JSON.stringify(en(e))});if(n.status!==201)throw Error(`Create cron job failed: ${n.status} ${await n.text()}`);return await n.json()}async listCrons(){let e=await this.fetchJson(`${this.baseUrl}/v1/crons`,{method:"GET",headers:this.apiKeyHeaders()});if(!e.ok)throw Error(`List cron jobs failed: ${e.status} ${await e.text()}`);return(await e.json()).crons}async getCron(e){let n=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}`,{method:"GET",headers:this.apiKeyHeaders()});if(n.status===404)return null;if(!n.ok)throw Error(`Get cron job failed: ${n.status} ${await n.text()}`);return await n.json()}async listCronRuns(e,n={}){let t=new URLSearchParams;if(n.limit!==void 0)t.set("limit",String(n.limit));let o=t.size>0?`?${t}`:"",r=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}/runs${o}`,{method:"GET",headers:this.apiKeyHeaders()});if(!r.ok)throw Error(`List cron job runs failed: ${r.status} ${await r.text()}`);return(await r.json()).runs}async updateCron(e,n){let t=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}`,{method:"PATCH",headers:this.apiKeyHeaders(),body:JSON.stringify(n)});if(!t.ok)throw Error(`Update cron job failed: ${t.status} ${await t.text()}`);return await t.json()}async deleteCron(e){let n=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}`,{method:"DELETE",headers:this.apiKeyHeaders()});if(n.status===404)return!1;if(!n.ok)throw Error(`Delete cron job failed: ${n.status} ${await n.text()}`);return(await n.json()).deleted}scopedUrl(e){if(e.projectSlug&&e.stageSlug&&e.endpointId)return`${this.baseUrl}/v1/projects/${encodeURIComponent(e.projectSlug)}/stages/${encodeURIComponent(e.stageSlug)}/agents/${encodeURIComponent(e.endpointId)}`;return`${this.baseUrl}/v1/runs`}asyncAgentRun(e,n){return{...e,conversationKey:n,poll:()=>this.getAsyncStatus(e),wait:(t)=>this.waitForAsyncStatus(e,t)}}async postAcceptedRun(e,n,t){let o=await this.fetchJson(e,{method:"POST",headers:this.apiKeyHeaders(),body:JSON.stringify(n)});if(o.status!==202)throw Error(`${t} failed: ${o.status} ${await nn(o,"202 JSON")}`);return this.asyncAgentRun(J(await o.json(),n),n.conversationKey)}async openStream(e,n){if(this.apiKey)return await this.fetchCore(e,n,{Authorization:`Bearer ${this.apiKey}`});throw Error(`BroodsClient streams directly from the core service at ${this.baseUrl}. Provide apiKey. For a self-hosted core service, set host/baseUrl or BROODS_HOST/BROODS_BASE_URL.`)}async fetchCore(e,n,t){try{return await this.fetchImpl(n,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t},body:JSON.stringify(e)})}catch(o){throw Error(`Cannot access the broods core service at ${n}. The SDK uses ${z} by default; set host/baseUrl or BROODS_HOST/BROODS_BASE_URL to your own core service URL if your account uses a custom deployment. Cause: ${o instanceof Error?o.message:String(o)}`)}}apiKeyHeaders(){if(!this.apiKey)throw Error("BroodsClient requires apiKey or BROODS_API_KEY.");return{"Content-Type":"application/json",Authorization:`Bearer ${this.apiKey}`}}async fetchJson(e,n){try{return await this.fetchImpl(e,{...n,headers:{"Content-Type":"application/json",...n.headers}})}catch(t){throw Error(`Cannot access the broods core service at ${e}. Cause: ${t instanceof Error?t.message:String(t)}`)}}resolveStatusUrl(e){if(typeof e!=="string")return e.statusUrl;if(/^https?:\/\//.test(e))return e;return on(this.baseUrl,e)}}function V(e){let n=e.trim(),t=/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(n)?n:`https://${n}`;return f(t)}function q(e,n){let t=e.eventId??`${n}-${Date.now()}`;return{agentId:e.agentId,eventId:t,conversationKey:e.conversationKey??t,events:B(e),...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}}function $e(e){if(typeof e==="string")return e;if(!e||typeof e!=="object")return String(e);let n=e,t=n.data?.error?.message??n.message??n.responseBody??JSON.stringify(e),o=n.name?`${n.name}: `:"",r=n.statusCode?` (HTTP ${n.statusCode})`:"";return`${o}${t}${r}`}function J(e,n){if(!e||typeof e!=="object")throw Error("Async response must be an object");let t=e.statusUrl;if(typeof t!=="string"||t.length===0)throw Error("Async response missing statusUrl");let o=typeof e.runId==="string"?e.runId:_e(t);if(!o)throw Error("Async response missing runId");let r=typeof e.eventId==="string"?e.eventId:o,{status:s,requestedMode:i}=e;return{statusUrl:t,runId:o,eventId:r,agentId:n.agentId,...s==="accepted"||s==="queued"||s==="applied"||s==="processing"?{status:s}:{},...i==="reject"||i==="followup"||i==="collect"||i==="steer"?{requestedMode:i}:{}}}function _e(e){let n=new URL(e).pathname.match(/\/v1\/runs\/([^/]+)$/);return n?.[1]?decodeURIComponent(n[1]):void 0}function en(e){if("agentId"in e)return e;let n=e.agent,t=typeof n==="string"?n:n.id,{agent:o,...r}=e;return{...r,agentId:t}}async function nn(e,n){if((e.headers.get("content-type")??"").toLowerCase().includes("text/event-stream"))return await e.body?.cancel().catch(()=>{}),`expected ${n}, but the server returned an SSE stream. This usually means the core deployment ignored the background flag and ran the request on the direct streaming runner.`;let o=await e.text();if(o.length<=2000)return o;return`${o.slice(0,2000)}... [truncated ${o.length-2000} chars]`}function tn(e,n){return new Promise((t,o)=>{if(n?.aborted){o(Error("Async status polling aborted."));return}let r=setTimeout(t,e);n?.addEventListener("abort",()=>{clearTimeout(r),o(Error("Async status polling aborted."))},{once:!0})})}function on(e,n){return`${V(e)}/v1/runs/${encodeURIComponent(n)}`}var rn=2000,Y=0,b=1;class Pe{baseUrl;apiKey;WebSocketImpl;connectTimeoutMs;constructor(e={}){if(h(),this.baseUrl=re(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||z),this.apiKey=e.apiKey||process.env.BROODS_API_KEY||"",!this.apiKey)throw Error("BroodsWebSocketClient requires apiKey or BROODS_API_KEY.");this.WebSocketImpl=e.WebSocket,this.connectTimeoutMs=e.connectTimeoutMs??rn}subscribe(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=sn(e),s=oe(this.baseUrl),i=new t(o,E(this.apiKey)),a=!1,u=!1,l=setTimeout(()=>{if(!a)m(s)},this.connectTimeoutMs),x=(c=1000,I="client closed")=>{if(u)return;if(u=!0,clearTimeout(l),e.signal?.removeEventListener("abort",R),i.readyState===b||i.readyState===Y)i.close(c,I)},m=(c)=>{n.onError?.(c),x(1011,"websocket error")},ue=()=>{n.onDone?.(),x(1000,"done")},R=()=>{if(i.readyState===b)i.send(JSON.stringify({type:"cancel"}));m(Error("WebSocket run aborted."))};return e.signal?.addEventListener("abort",R,{once:!0}),i.onopen=()=>{if(a=!0,clearTimeout(l),e.signal?.aborted){R();return}i.send(JSON.stringify({type:"execute",agentId:r,...e.answers?{answers:e.answers}:{events:B(e)},sessionId:e.sessionId,...e.eventId!==void 0?{eventId:e.eventId}:{},...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}))},i.onmessage=(c)=>{if(typeof c.data!=="string")return;let I=Q(c.data);if(!I)return;let k=ee(I,n);switch(n.onMessage?.(k),k.type){case"meta":n.onMeta?.(k);break;case"done":ue();break;case"error":m(Error(X(k.error)));break}},i.onerror=()=>{m(s)},i.onclose=(c)=>{if(clearTimeout(l),e.signal?.removeEventListener("abort",R),u||c.code===1000)return;m(Error(c.reason||"WebSocket connection closed."))},{url:o,sendControl:function(c){if(i.readyState!==b)throw Error("WebSocket is not open");i.send(JSON.stringify({type:"control",...c}))},close:x}}attach(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=new t(o,E(this.apiKey)),s=!1,i=(a=1000,u="client closed")=>{if(s)return;if(s=!0,r.readyState===b||r.readyState===Y)r.close(a,u)};return r.onopen=()=>r.send(JSON.stringify({type:"attach",...e,signal:void 0,agent:void 0})),r.onmessage=(a)=>{if(typeof a.data!=="string")return;let u=Q(a.data);if(!u)return;let l=ee(u,n);if(n.onMessage?.(l),l.type==="done")n.onDone?.();if(l.type==="error")n.onError?.(Error(X(l.error)))},r.onerror=()=>n.onError?.(oe(this.baseUrl)),r.onclose=(a)=>{if(!s&&a.code!==1000)n.onError?.(Error(a.reason||"WebSocket connection closed."))},{url:o,sendControl:function(a){if(r.readyState!==b)throw Error("WebSocket is not open");r.send(JSON.stringify({type:"control",...a}))},close:i}}async*stream(e){let n=[],t=!1,o=null,r=null,s=()=>{r?.(),r=null},i=this.subscribe(e,{onMessage:function(a){n.push(a),s()},onDone:function(){t=!0,s()},onError:function(a){o=a,s()}});try{while(!0){if(n.length>0){yield n.shift();continue}if(o)throw o;if(t)return;await new Promise((a)=>{r=a})}}finally{i.close()}}buildUrl(e){let n=an(e),t=e.projectSlug??e.agent?.projectSlug,o=e.stageSlug??e.agent?.stageSlug,r=t&&o?`/projects/${encodeURIComponent(t)}/stages/${encodeURIComponent(o)}`:"";return`${K(this.baseUrl)}/v1${r}/agents/${encodeURIComponent(n)}/ws`}resolveWebSocket(){let e=this.WebSocketImpl??globalThis.WebSocket;if(!e)throw Error("WebSocket is not available. Pass a WebSocket implementation in BroodsWebSocketClient options.");return e}}function K(e){let n=new URL(re(e));if(n.protocol==="https:")n.protocol="wss:";if(n.protocol==="http:")n.protocol="ws:";return f(n.toString())}function E(e){return["broods.v1",`broods.token.${e}`]}function X(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&typeof e.message==="string")return e.message;return e===void 0?"WebSocket stream error.":JSON.stringify(e)}function re(e){let n=e.trim();if(/^wss?:\/\//.test(n))return f(n);return V(n)}function Q(e){try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}function sn(e){let n=e.agentId??e.agent?.id??e.endpointId;if(!n)throw Error("WebSocket run requires agent, agentId, or endpointId.");return n}function an(e){let n=e.endpointId??e.agent?.endpointId??e.agent?.id;if(!n)throw Error("WebSocket run requires agent or endpointId.");return n}function ee(e,n){if(e.type!=="output")return e;let t=e;return n.onOutput?.(t),t.data}function oe(e){return Error(`Cannot access the WebSocket service at ${e}.`)}var ie=Symbol.for("broods.resource"),ae=Symbol.for("broods.config"),ce=Symbol.for("broods.connection"),se=/^[A-Z][A-Z0-9_]{0,63}$/,Me=new Proxy((e)=>{if(!se.test(e))throw Error("env name must match /^[A-Z][A-Z0-9_]*$/ and be at most 64 characters.");return{__beeblastEnv:!0,name:e}},{get:function(e,n,t){if(typeof n==="string"&&se.test(n))throw Error(`env.${n} is not supported; use env("${n}")`);return Reflect.get(e,n,t)}});function Ne(e){let{name:n,description:t,...o}=e;return d("agent",n,t,o)}function je(e){return{[ae]:!0,config:e}}function qe(e){let{name:n,description:t,...o}=e;return d("cron",n,t,o)}function Le(e){return e}function De(e){let{name:n,description:t,...o}=e;return d("mcp",n,t,o)}function Ue(e){let{name:n,description:t,...o}=e;return d("policy",n,t,o)}function Be(e){let{name:n,description:t,...o}=e;return d("sandbox",n,t,o)}function Fe(e){let{name:n,description:t,...o}=e;return d("skill",n,t,o)}function Ze(e){let{name:n,description:t,...o}=e;return d("workspace",n,t,o)}function He(e){return y("discord",e)}function Ve(e){return y("github",e)}function Ke(e){return y("matrix",e)}function We(e){return y("pancake",e)}function Ge(e){return y("slack",e)}function Je(e){return y("telegram",e)}function Ye(e){return y("zalo",e)}function Xe(e){let{name:n,description:t,channelId:o,guildId:r,...s}=e;return p(n,t,o,r,s)}function Qe(e){let{name:n,description:t,repo:o,...r}=e,[s,...i]=o.split("/");if(!s||i.length!==1||!i[0])throw Error(`Channel "${n}" repo must be "owner/name", not "${o}"`);return p(n,t,o,s,r)}function et(e){let{name:n,description:t,channelId:o,...r}=e;return p(n,t,o,void 0,r)}function tt(e){let{name:n,description:t,conversationId:o,...r}=e;return p(n,t,o,void 0,r)}function nt(e){let{name:n,description:t,channelId:o,teamId:r,...s}=e;return p(n,t,o,r,s)}function rt(e){let{name:n,description:t,chatId:o,...r}=e;return p(n,t,o,void 0,r)}function ot(e){let{name:n,description:t,chatId:o,...r}=e;return p(n,t,o,void 0,r)}function ne(e){return Boolean(e&&typeof e==="object"&&e[ae])}function w(e){return Boolean(e&&typeof e==="object"&&e[ce])}function g(e){return Boolean(e&&typeof e==="object"&&e[ie])}function p(e,n,t,o,r){return d("channelRecord",e,n,{...r,externalId:t,...o?{workspaceRef:o}:{}})}function y(e,n){let{partition:t,...o}=n;return{[ce]:!0,kind:"connection",type:e,...t?{partition:t}:{},config:o}}function d(e,n,t,o){return{[ie]:!0,kind:e,name:n,...t?{description:t}:{},config:o}}
|
|
5
|
+
export{B,me,xe,Ce,Oe,Ae,F,ze,S,v,C,Z,H,_,f,te,h,O,z,he,j,V,Pe,K,E,Me,Ne,je,qe,Le,De,Ue,Be,Fe,Ze,He,Ve,Ke,We,Ge,Je,Ye,Xe,Qe,et,tt,nt,rt,ot,ne,w,g};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{E}from"./chunk-
|
|
1
|
+
import{E}from"./chunk-9ex5d29v.js";import{e,o,a,l,n,t,d,R,s,p,r}from"./chunk-js5cjmhp.js";import{de,pe}from"./cli/index.js";import{spawn as V}from"node:child_process";import{hostname as ee}from"node:os";import{performance as T}from"node:perf_hooks";var j=["cursor_position","double_click","hold_key","key","left_click","left_click_drag","left_mouse_down","left_mouse_up","middle_click","mouse_move","right_click","screenshot","scroll","triple_click","type","wait","zoom"];var k={badFrame:{code:4400,reason:"Malformed frame"},occupied:{code:4423,reason:"Already connected from another daemon"},replaced:{code:4409,reason:"Replaced by a newer connection"},unauthorized:{code:4401,reason:"Unauthorized; check BROODS_API_KEY"},unknownSandbox:{code:4404,reason:"No machine sandbox with that name in this account"}},N="/v1/machines/ws",H=t({action:p(j),coordinate:n(o().int()).length(2).optional().describe("[x, y] in screenshot pixels for mouse actions."),start_coordinate:n(o().int()).length(2).optional().describe("[x, y] where a left_click_drag starts."),text:e().optional().describe("Text for type, the key chord for key and hold_key, or modifiers to hold during a click, drag or scroll."),scroll_direction:p(["down","left","right","up"]).optional(),scroll_amount:o().int().min(1).optional().describe("Scroll clicks, default 3."),duration:o().min(0).max(300).optional().describe("Seconds for wait and hold_key."),region:n(o().int()).length(4).optional().describe("[x0, y0, x1, y1] of the screenshot to zoom into."),repeat:o().int().min(1).max(100).optional().describe("How many times to press the key.")}),P=H.extend({type:r("computer"),id:e()}),U=t({type:r("computer-result"),id:e(),text:e().optional(),image:t({data:e(),mediaType:e()}).optional(),app:e().optional(),error:e().optional()}),B=t({type:r("exec"),id:e(),code:e(),cwd:e().optional(),env:s(e(),e()).optional(),timeoutSeconds:o().positive(),outputLimitBytes:o().positive()}),K=t({type:r("hello"),sandbox:e().min(1),hostname:e().optional(),platform:e().optional(),computer:a().optional(),mcp:n(e()).optional(),instance:e().optional(),force:a().optional()}),W=t({type:r("mcp-call"),id:e(),server:e(),tool:e(),args:s(e(),l())}),G=t({type:r("mcp-list"),id:e(),server:e()}),J=t({type:r("mcp-result"),id:e(),result:d({content:n(l())}).optional(),error:e().optional()}),X=t({type:r("mcp-tools"),id:e(),tools:n(d({name:e(),inputSchema:s(e(),l())})).optional(),error:e().optional()}),Y=t({type:r("ready"),sandboxId:e()}),q=t({type:r("result"),id:e(),exitCode:o().nullable(),stdout:e(),stderr:e(),durationMs:o(),timedOut:a(),truncated:a()}),Z=R("type",[P,B,W,G,Y]),me=R("type",[U,K,J,X,q]);function O(i){let c=new URL(N,i);return c.protocol=c.protocol==="https:"?"wss:":"ws:",c.toString()}function D(i){return Q(Z,i)}function Q(i,c){if(typeof c!=="string")return null;try{let u=i.safeParse(JSON.parse(c));return u.success?u.data:null}catch{return null}}var te=new Set([k.occupied.code,k.replaced.code,k.unauthorized.code,k.unknownSandbox.code]),L=72,z=30000,A=1000;function oe(i,c,u){return new Promise((y)=>{let m=T.now(),b=new S(i.outputLimitBytes),h=new S(i.outputLimitBytes),M=!1,_=!1,w=(v,C)=>{if(_)return;if(_=!0,clearTimeout(g),u?.removeEventListener("abort",f),C)h.append(Buffer.from(`${C}
|
|
2
2
|
`));y({type:"result",id:i.id,exitCode:v,stdout:b.text(),stderr:h.text(),durationMs:Math.round(T.now()-m),timedOut:M,truncated:b.truncated||h.truncated})},x=V("bash",["-lc",i.code],{cwd:i.cwd??c,env:{...process.env,...i.env},detached:!0,stdio:["ignore","pipe","pipe"]}),F=()=>{if(!x.pid)return;try{process.kill(-x.pid,"SIGKILL")}catch{x.kill("SIGKILL")}},g=setTimeout(()=>{M=!0,F()},i.timeoutSeconds*1000),f=()=>{F(),w(null,"stopped: the daemon closed its socket")};if(u?.addEventListener("abort",f,{once:!0}),x.stdout.on("data",(v)=>b.append(v)),x.stderr.on("data",(v)=>h.append(v)),x.on("error",(v)=>w(null,v.message)),x.on("close",(v)=>w(v)),u?.aborted)f()})}async function Fe(i){let c=pe(),u=crypto.randomUUID(),y=i.mcpFile?await ie(i.mcpFile,i.log):null,m=i.computer?await ne(i.log):null,b=A;try{while(!i.signal.aborted){let h=Date.now(),M=await ce(i,u,c,m,y);if(i.signal.aborted)return;if(te.has(M.code))throw Error(M.reason||`core closed the socket (${M.code})`);if(Date.now()-h>z)b=A;i.log(`disconnected (${M.reason||M.code}), reconnecting in ${Math.round(b/1000)}s`),await de(b,i.signal),b=Math.min(b*2,z)}}finally{m?.stop(),await y?.stop()}}class S{#o=[];#e;#t=0;truncated=!1;constructor(i){this.#e=i}append(i){if(this.#t>=this.#e){this.truncated=!0;return}let c=this.#e-this.#t;if(i.byteLength>c){this.#o.push(i.subarray(0,c)),this.#t=this.#e,this.truncated=!0;return}this.#o.push(i),this.#t+=i.byteLength}text(){let i=Buffer.concat(this.#o).toString("utf8");return this.truncated?`${i}
|
|
3
3
|
[output truncated]`:i}}function re(i){let c=[i.action];if(i.coordinate)c.push(`at ${i.coordinate.join(",")}`);if(i.text!==void 0)c.push(JSON.stringify(I(i.text)));if(i.region)c.push(`region ${i.region.join(",")}`);return c.join(" ")}function I(i){let c=i.trim().split(`
|
|
4
4
|
`)[0]??"";return c.length>L?`${c.slice(0,L)}…`:c}async function ne(i){let{startDesktop:c}=await import("./chunk-5tnnqapc.js"),{display:u,driver:y,permissions:m}=await c(!1);if(i(`computer use on, ${u.width}x${u.height} screenshots`),!m.screenRecording||!m.accessibility)i(" screen recording or accessibility is missing, run `broods machine --doctor --request`");return y}async function ie(i,c){let{McpHost:u,readMcpServersFile:y}=await import("./chunk-ck8t5hr5.js"),m=new u(y(i),c);return c(`mcp servers from ${i}: ${m.names().join(", ")}`),m}async function se(i,c,u){try{if(i.type==="mcp-list"){let m=await c.listTools(i.server);return u(` mcp ${i.server}: ${m.length} tools`),{type:"mcp-tools",id:i.id,tools:m}}u(` mcp ${i.server}.${i.tool}`);let y=await c.callTool(i.server,i.tool,i.args);return{type:"mcp-result",id:i.id,result:y}}catch(y){let m=y instanceof Error?y.message:String(y);return u(` mcp ${i.server}: ${m}`),{type:i.type==="mcp-call"?"mcp-result":"mcp-tools",id:i.id,error:m}}}function ce(i,c,u,y,m){return new Promise((b)=>{let h=new u(O(i.baseUrl),E(i.apiKey)),M=new AbortController,_=()=>h.close(1000,"daemon stopped"),w=(F)=>{if(h.readyState===h.OPEN)h.send(JSON.stringify(F))},x=(F,g)=>{i.signal.removeEventListener("abort",_),M.abort(),b({code:F,reason:g})};i.signal.addEventListener("abort",_,{once:!0}),h.onopen=()=>w({type:"hello",sandbox:i.sandbox,hostname:ee(),platform:process.platform,computer:y!==null,mcp:m?.names(),instance:c,force:i.force}),h.onmessage=(F)=>{let g=D(F.data);if(g?.type==="ready"){i.log(`connected as ${i.sandbox} (${g.sandboxId})`);return}if(g?.type==="computer"&&y){i.log(` ${re(g)}`),y.run(g).then((f)=>{if(f.error)i.log(` error: ${f.error}`);w(f)});return}if((g?.type==="mcp-call"||g?.type==="mcp-list")&&m){se(g,m,i.log).then(w);return}if(g?.type!=="exec")return;i.log(`$ ${I(g.code)}`),oe(g,i.cwd,M.signal).then((f)=>{i.log(` exit ${f.exitCode??"none"} in ${f.durationMs}ms${f.timedOut?" (timed out)":""}`),w(f)})},h.onerror=()=>x(1006,"connection failed"),h.onclose=(F)=>x(F.code,F.reason)})}export{Fe as runMachineDaemon};
|
package/dist/cli/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{F,S,v,C,Z,H,_,f,te,h,O,z,j,K,E,ne,w,g}from"../chunk-
|
|
2
|
+
import{F,S,v,C,Z,H,_,f,te,h,O,z,j,K,E,ne,w,g}from"../chunk-9ex5d29v.js";import{chmod as Tr,lstat as Ur,mkdir as pn,readFile as kt,readdir as Lr,stat as Nr,writeFile as V}from"node:fs/promises";import{createHash as St}from"node:crypto";import{basename as Br,join as Oe,relative as Mr,resolve as A,sep as Kr}from"node:path";import{watch as Gr}from"node:fs";import{spawn as $t}from"node:child_process";import{tmpdir as Wr}from"node:os";import{performance as pt}from"node:perf_hooks";import{stripVTControlCharacters as Fr}from"node:util";import{fileURLToPath as Lt,pathToFileURL as Un}from"node:url";import{createHash as Nt}from"node:crypto";import{readFileSync as Bt}from"node:fs";import{mkdtemp as Ln,readdir as Nn,readFile as Mt,rm as Bn,writeFile as He}from"node:fs/promises";import Cn from"node:module";import{tmpdir as Mn}from"node:os";import{basename as Kt,isAbsolute as Gt,join as Q,relative as ge,resolve as Ae}from"node:path";import{build as Wt,transformSync as Kn}from"esbuild";var En={anthropic:{label:"Anthropic",modelPlaceholder:"claude-sonnet-4-5-20250929"},azure:{label:"Azure OpenAI",modelPlaceholder:"gpt-4.1-mini"},baseten:{label:"Baseten",modelPlaceholder:"deepseek-ai/DeepSeek-V3"},bedrock:{label:"Amazon Bedrock",modelPlaceholder:"anthropic.claude-sonnet-4-5-20250929-v1:0"},cerebras:{label:"Cerebras",modelPlaceholder:"llama3.1-8b"},cohere:{label:"Cohere",modelPlaceholder:"command-a-03-2025"},custom:{label:"Custom OpenAI-compatible",modelPlaceholder:"gpt-oss-120b"},deepinfra:{label:"DeepInfra",modelPlaceholder:"deepseek-ai/DeepSeek-V3"},deepseek:{label:"DeepSeek",modelPlaceholder:"deepseek-chat"},fireworks:{label:"Fireworks",modelPlaceholder:"accounts/fireworks/models/deepseek-v3"},google:{label:"Google",modelPlaceholder:"gemini-2.5-flash"},groq:{label:"Groq",modelPlaceholder:"llama-3.3-70b-versatile"},minimax:{label:"MiniMax",modelPlaceholder:"MiniMax-M2.7"},mistral:{label:"Mistral",modelPlaceholder:"mistral-large-latest"},openai:{label:"OpenAI",modelPlaceholder:"gpt-4.1-mini"},perplexity:{label:"Perplexity",modelPlaceholder:"sonar-pro"},togetherai:{label:"Together.ai",modelPlaceholder:"deepseek-ai/DeepSeek-V3"},v0:{label:"Vercel v0",modelPlaceholder:"v0-1.0-md"},vercel:{label:"Vercel AI Gateway",modelPlaceholder:"openai/gpt-4.1-mini"},vertex:{label:"Google Vertex AI",modelPlaceholder:"gemini-2.5-flash"},xai:{label:"xAI Grok",modelPlaceholder:"grok-4"}},On=Object.keys(En);function Rn(e){return Object.hasOwn(En,e)}var we="*",Ft=`const passthrough = (input) => input;
|
|
3
3
|
export const defineAgent = passthrough;
|
|
4
4
|
export const defineBroods = passthrough;
|
|
5
5
|
export const defineCron = passthrough;
|
|
@@ -8,6 +8,8 @@ export const defineDiscordConnection = passthrough;
|
|
|
8
8
|
export const defineGitHubChannel = passthrough;
|
|
9
9
|
export const defineGitHubConnection = passthrough;
|
|
10
10
|
export const defineHarness = passthrough;
|
|
11
|
+
export const defineMatrixChannel = passthrough;
|
|
12
|
+
export const defineMatrixConnection = passthrough;
|
|
11
13
|
export const defineMcp = passthrough;
|
|
12
14
|
export const definePancakeChannel = passthrough;
|
|
13
15
|
export const definePancakeConnection = passthrough;
|
|
@@ -71,7 +73,7 @@ Check the browser tab and the dashboard logs for an error. If the browser shows
|
|
|
71
73
|
404 on /cli-auth/start, deploy the dashboard build that includes CLI auth or pass
|
|
72
74
|
--dashboard-url for the environment you deployed. Other common causes are missing
|
|
73
75
|
cliAuth Convex functions or no active API account (Settings -> API Access).`)),n)});try{return await Promise.race([e,o])}finally{if(t)clearTimeout(t)}}import{existsSync as it}from"node:fs";import{mkdir as vr,readFile as kr,writeFile as Sr}from"node:fs/promises";import{dirname as lt,join as rn,resolve as $r,sep as ie}from"node:path";import{fileURLToPath as Er}from"node:url";var sn=rn(lt(C),"update-check.json"),Or=86400000,Rr="https://registry.npmjs.org/broods/latest",Cr=2000;function an(e,n){let t=ct(e),o=ct(n);for(let r=0;r<3;r+=1){let s=t[r]??0,i=o[r]??0;if(s!==i)return s>i}return!at(e)&&at(n)}async function cn(e={}){let n=await jr(),t=e.maxAgeMs??Or;if(n&&Date.now()-n.checkedAt<t)return n.latest;let o=await Ar();if(o===null)return n?.latest??null;return await Pr({checkedAt:Date.now(),latest:o}),o}function dt(e=$r(process.cwd()),n=Er(import.meta.url)){let t=`${ie}node_modules${ie}`,o=n.lastIndexOf(t),r=o===-1?null:n.slice(0,o),s=r===null?n.startsWith(`${e}${ie}`):e===r||e.startsWith(`${r}${ie}`),a=n.includes(`${ie}.bun${ie}install${ie}global${ie}`)||s&&xr(r??e)?"bun":"npm",c=a==="bun"?"add":"install";return{manager:a,global:!s,command:a,args:s?[c,"broods@latest"]:[c,"-g","broods@latest"]}}async function Ar(){try{let e=await fetch(Rr,{signal:AbortSignal.timeout(Cr),headers:{accept:"application/json"}});if(!e.ok)return null;let n=await e.json();return typeof n.version==="string"?n.version:null}catch{return null}}function xr(e){return it(rn(e,"bun.lock"))||it(rn(e,"bun.lockb"))}function at(e){return e.includes("-")}async function jr(){try{let e=JSON.parse(await kr(sn,"utf8"));if(typeof e.latest!=="string")return null;if(typeof e.checkedAt!=="number")return null;return{checkedAt:e.checkedAt,latest:e.latest}}catch{return null}}function ct(e){let[n]=e.trim().replace(/^v/,"").split("-");return(n??"").split(".").slice(0,3).map((t)=>Number.parseInt(t,10)||0)}async function Pr(e){try{await vr(lt(sn),{recursive:!0}),await Sr(sn,`${JSON.stringify(e)}
|
|
74
|
-
`,"utf8")}catch{}}var ut={name:"broods",version:"0.
|
|
76
|
+
`,"utf8")}catch{}}var ut={name:"broods",version:"0.38.1",description:"CLI + TypeScript SDK for the broods agent platform.",keywords:["agents","ai","broods","cli","sdk"],homepage:"https://github.com/beeblastco/broods#readme",bugs:{url:"https://github.com/beeblastco/broods/issues"},license:"MIT",repository:{type:"git",url:"git+https://github.com/beeblastco/broods.git",directory:"packages/broods"},bin:{broods:"dist/cli/index.js"},files:["dist","README.md","LICENSE.md"],type:"module",main:"./dist/index.js",types:"./dist/index.d.ts",typesVersions:{"*":{account:["./dist/account.d.ts"]}},exports:{".":{types:"./dist/index.d.ts",import:"./dist/index.js"},"./account":{types:"./dist/account.d.ts",import:"./dist/account.js"}},scripts:{build:"bun scripts/build.ts && rollup -c rollup.dts.config.mjs && rm -rf .dts-temp",check:"tsc --noEmit","pack:check":"bun run build && publint && attw --pack .",test:"bun test"},dependencies:{"@modelcontextprotocol/client":"^2.0.0",esbuild:"^0.28.2"},devDependencies:{"@ai-sdk/tui":"1.0.108","@arethetypeswrong/cli":"^0.18.5","@chat-adapter/discord":"^4.38.1","@chat-adapter/github":"^4.38.1","@chat-adapter/slack":"^4.38.1","@chat-adapter/telegram":"^4.38.1","@modelcontextprotocol/server":"2.0.0","@types/bun":"^1.3.14","@typescript/typescript6":"6.0.2",ai:"^7.0.107",publint:"^0.3.23",rollup:"^4.62.4","rollup-plugin-dts":"^6.5.1",typescript:"^7.0.2",zod:"^4.4.3"},peerDependencies:{ai:"^7.0.107"},engines:{node:">=22.15"}};var gt=`---
|
|
75
77
|
name: broods
|
|
76
78
|
description: Work on a broods account alongside a developer from Claude Code or a development agent. Covers onboarding and sign-in, creating a broods project, defining and deploying agents and their resources with the CLI, and integrating a deployed agent into existing code with the SDK. Use when asked to set up broods, create or work on a broods project, create or manage agents or any account resource, or call a deployed agent from application code.
|
|
77
79
|
---
|
|
@@ -385,13 +387,13 @@ ${L("stage")}`);let i=h(),a=b(e,"--dashboard-url")??i.dashboardUrl??J,c=Ge(e),d=
|
|
|
385
387
|
|
|
386
388
|
${L("env")}`);if(a&&!t)throw Error(`broods env ${n} needs a variable name.
|
|
387
389
|
|
|
388
|
-
${L("env")}`);let{manifest:c,config:d}=await ee({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),l=await G(b(e,"--base-url")??d.baseUrl),u=new D({baseUrl:l.baseUrl,token:l.token}),p=`${c.project}/${c.stage}`;if(i){await Rs(u,c,p);return}if(o){let y=await u.listEnv(c.project,c.stage);if(y.length===0){console.log(`No environment variables set for ${p}.`);return}console.log(`Environment variables for ${p} (values hidden):`);for(let k of y)console.log(` ${k.name}`);return}if(s){let y=await u.getEnv(c.project,c.stage,t);if(y===null){console.error(`${t} is not set for ${p}`),process.exitCode=1;return}console.log(y);return}if(r){await u.removeEnv(c.project,c.stage,t),console.log(`Removed ${t} from ${p}`);return}let m=await rt(t);await u.setEnv(c.project,c.stage,t,m),console.log(`Stored ${t} for ${p}`)}async function Rs(e,n,t){let o=await hn(e,n);if(o.length===0){console.log('No env("NAME") references in this project.');return}let r=await xt(e,n,o);if(r.length>0)tn(r);let s=Ee(o,"synced").length;console.log(r.length>0?`${s} other referenced variable(s) already in step with ${t}.`:`${s} referenced variable(s) already in step with ${t}.`);let i=Ee(o,"stage-only");if(i.length>0)console.log(`${i.length} referenced variable(s) live only on ${t}: ${i.join(", ")}`);let a=Ee(o,"unresolved");if(a.length>0)x(`⚠ ${a.length} referenced variable(s) with no value here or on ${t}: ${a.join(", ")}. Put them in .env.local, or run \`broods env set <NAME>\`.`)}function We(){h();let e=process.env.BROODS_API_KEY??"";if(!e)throw Error("BROODS_API_KEY is not set. Run `broods deploy` first, or set the key in .env.local.");let n=process.env.BROODS_BASE_URL??process.env.BROODS_HOST??z;return{apiKey:e,baseUrl:n}}function bn(e){if(P(e,"--all"))return"DEBUG";let n=b(e,"--level");if(n===void 0&&P(e,"--level"))throw Error("Missing value for --level. Use DEBUG, INFO, WARN, or ERROR.");if(!n)return"WARN";let t=n.toUpperCase();if(t==="DEBUG")return"DEBUG";if(t==="INFO")return"INFO";if(t==="WARN"||t==="WARNING")return"WARN";if(t==="ERROR")return"ERROR";throw Error(`Unknown log level: ${n}. Use DEBUG, INFO, WARN, or ERROR.`)}async function Cs(e){h();let n=b(e,"--project")??process.env.BROODS_PROJECT,t=b(e,"--stage")??_();if(!n)throw Error("Project name is required. Pass --project <name> or set BROODS_PROJECT in .env.local.");if(!t)throw Error("Stage name is required. Pass --stage <name> or set BROODS_STAGE in .env.local.");return{project:n,stage:t}}async function wn(e,n){let t=await Cs(e),o=await nt(n.baseUrl,n.apiKey);if(!o)return t;if(o.projectSlug!==t.project||o.stageSlug!==t.stage)console.log(`· reading ${o.projectSlug}/${o.stageSlug}. The runtime key is scoped there, not to ${t.project}/${t.stage}.`);return{project:o.projectSlug,stage:o.stageSlug}}function jt(e){return e==="WARN"?" (--all for INFO too)":""}function yn(e){let n=new Date(e.ts).toISOString().slice(11,23),t=e.level.padEnd(5),o=Fr(e.message);return`${n} ${t} ${e.eventType} ${o}`}async function As(e){let{apiKey:n,baseUrl:t}=We(),{project:o,stage:r}=await wn(e,{baseUrl:t,apiKey:n}),s=bn(e),i=new AbortController,a=()=>i.abort();process.on("SIGINT",a),console.log(`Streaming live logs for ${o}/${r} [${s}+]`+jt(s)+", Ctrl+C to stop");try{for await(let c of Te({baseUrl:t,apiKey:n,project:o,stage:r},{backfill:0,minLevel:s,signal:i.signal}))console.log(yn(c))}catch(c){if(!i.signal.aborted)console.error(c instanceof Error?c.message:String(c)),process.exitCode=1}finally{process.off("SIGINT",a)}}async function xs(e){if(P(e,"--doctor")){await js(P(e,"--request"));return}let n=se(e)[0];if(!n){console.log(mn.machine),process.exitCode=1;return}let{runMachineDaemon:t}=await import("../chunk-
|
|
390
|
+
${L("env")}`);let{manifest:c,config:d}=await ee({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),l=await G(b(e,"--base-url")??d.baseUrl),u=new D({baseUrl:l.baseUrl,token:l.token}),p=`${c.project}/${c.stage}`;if(i){await Rs(u,c,p);return}if(o){let y=await u.listEnv(c.project,c.stage);if(y.length===0){console.log(`No environment variables set for ${p}.`);return}console.log(`Environment variables for ${p} (values hidden):`);for(let k of y)console.log(` ${k.name}`);return}if(s){let y=await u.getEnv(c.project,c.stage,t);if(y===null){console.error(`${t} is not set for ${p}`),process.exitCode=1;return}console.log(y);return}if(r){await u.removeEnv(c.project,c.stage,t),console.log(`Removed ${t} from ${p}`);return}let m=await rt(t);await u.setEnv(c.project,c.stage,t,m),console.log(`Stored ${t} for ${p}`)}async function Rs(e,n,t){let o=await hn(e,n);if(o.length===0){console.log('No env("NAME") references in this project.');return}let r=await xt(e,n,o);if(r.length>0)tn(r);let s=Ee(o,"synced").length;console.log(r.length>0?`${s} other referenced variable(s) already in step with ${t}.`:`${s} referenced variable(s) already in step with ${t}.`);let i=Ee(o,"stage-only");if(i.length>0)console.log(`${i.length} referenced variable(s) live only on ${t}: ${i.join(", ")}`);let a=Ee(o,"unresolved");if(a.length>0)x(`⚠ ${a.length} referenced variable(s) with no value here or on ${t}: ${a.join(", ")}. Put them in .env.local, or run \`broods env set <NAME>\`.`)}function We(){h();let e=process.env.BROODS_API_KEY??"";if(!e)throw Error("BROODS_API_KEY is not set. Run `broods deploy` first, or set the key in .env.local.");let n=process.env.BROODS_BASE_URL??process.env.BROODS_HOST??z;return{apiKey:e,baseUrl:n}}function bn(e){if(P(e,"--all"))return"DEBUG";let n=b(e,"--level");if(n===void 0&&P(e,"--level"))throw Error("Missing value for --level. Use DEBUG, INFO, WARN, or ERROR.");if(!n)return"WARN";let t=n.toUpperCase();if(t==="DEBUG")return"DEBUG";if(t==="INFO")return"INFO";if(t==="WARN"||t==="WARNING")return"WARN";if(t==="ERROR")return"ERROR";throw Error(`Unknown log level: ${n}. Use DEBUG, INFO, WARN, or ERROR.`)}async function Cs(e){h();let n=b(e,"--project")??process.env.BROODS_PROJECT,t=b(e,"--stage")??_();if(!n)throw Error("Project name is required. Pass --project <name> or set BROODS_PROJECT in .env.local.");if(!t)throw Error("Stage name is required. Pass --stage <name> or set BROODS_STAGE in .env.local.");return{project:n,stage:t}}async function wn(e,n){let t=await Cs(e),o=await nt(n.baseUrl,n.apiKey);if(!o)return t;if(o.projectSlug!==t.project||o.stageSlug!==t.stage)console.log(`· reading ${o.projectSlug}/${o.stageSlug}. The runtime key is scoped there, not to ${t.project}/${t.stage}.`);return{project:o.projectSlug,stage:o.stageSlug}}function jt(e){return e==="WARN"?" (--all for INFO too)":""}function yn(e){let n=new Date(e.ts).toISOString().slice(11,23),t=e.level.padEnd(5),o=Fr(e.message);return`${n} ${t} ${e.eventType} ${o}`}async function As(e){let{apiKey:n,baseUrl:t}=We(),{project:o,stage:r}=await wn(e,{baseUrl:t,apiKey:n}),s=bn(e),i=new AbortController,a=()=>i.abort();process.on("SIGINT",a),console.log(`Streaming live logs for ${o}/${r} [${s}+]`+jt(s)+", Ctrl+C to stop");try{for await(let c of Te({baseUrl:t,apiKey:n,project:o,stage:r},{backfill:0,minLevel:s,signal:i.signal}))console.log(yn(c))}catch(c){if(!i.signal.aborted)console.error(c instanceof Error?c.message:String(c)),process.exitCode=1}finally{process.off("SIGINT",a)}}async function xs(e){if(P(e,"--doctor")){await js(P(e,"--request"));return}let n=se(e)[0];if(!n){console.log(mn.machine),process.exitCode=1;return}let{runMachineDaemon:t}=await import("../chunk-rk1v0qm8.js"),{apiKey:o,baseUrl:r}=We(),s=A(b(e,"--cwd")??process.cwd()),i=P(e,"--computer"),a=b(e,"--mcp"),c=P(e,"--force"),d=new AbortController,l=()=>d.abort();process.on("SIGINT",l),console.log(`Connecting ${n} to ${r} (cwd ${s}${i?", computer use on":""}), Ctrl+C to stop`);try{await t({apiKey:o,baseUrl:r,computer:i,cwd:s,force:c,log:(u)=>console.log(u),mcpFile:a?A(a):void 0,sandbox:n,signal:d.signal})}catch(u){console.error(u instanceof Error?u.message:String(u)),process.exitCode=1}finally{process.off("SIGINT",l)}}async function js(e){try{let{startDesktop:n}=await import("../chunk-5tnnqapc.js"),{display:t,driver:o,permissions:r}=await n(e);o.stop();let s=(i)=>i?"granted":"missing";if(console.log(`screenshot frame ${t.width}x${t.height} (scale ${t.scale.toFixed(2)})`),console.log(`screen recording ${s(r.screenRecording)}`),console.log(`accessibility ${s(r.accessibility)}`),!r.screenRecording||!r.accessibility)console.log(e?"Approve the prompts, or add this terminal under System Settings > Privacy & Security, then run again.":"Run `broods machine --doctor --request` to show the macOS prompts."),process.exitCode=1}catch(n){console.error(n instanceof Error?n.message:String(n)),process.exitCode=1}}async function Ps(e){let{apiKey:n,baseUrl:t}=We(),{project:o,stage:r}=await wn(e,{baseUrl:t,apiKey:n}),s=b(e,"--sandbox");if(P(e,"--sandbox")&&!F(s))throw Error("--sandbox needs the instance log id, the UUID shown in the dashboard Instances sheet.");let i=s?"DEBUG":bn(e),a=Number(b(e,"--limit")??b(e,"-n")??100),c=P(e,"--json"),d=new AbortController,l=()=>d.abort();process.on("SIGINT",l),console.log(`Logs for ${o}/${r}`+(s?` sandbox ${s}`:"")+` [${i}+]`+jt(i)+` (backfill ${a}), Ctrl+C to stop`);try{for await(let u of Te({baseUrl:t,apiKey:n,project:o,stage:r},{backfill:a,minLevel:i,...s?{sandboxId:s}:{},signal:d.signal}))if(c)console.log(JSON.stringify(u));else console.log(yn(u))}catch(u){if(!d.signal.aborted)console.error(u instanceof Error?u.message:String(u)),process.exitCode=1}finally{process.off("SIGINT",l)}}async function Is(e){let[n,t]=se(e);if(!n){console.log(L("agent"));return}if(n==="list"||n==="ls"){await Ds(e);return}if(n==="get"){await _s(t,e);return}throw Error(`Unknown agent subcommand: ${n}
|
|
389
391
|
|
|
390
392
|
${L("agent")}`)}async function Pt(e){let{manifest:n,config:t}=await ee({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),o=await G(b(e,"--base-url")??t.baseUrl),r=await new D({baseUrl:o.baseUrl,token:o.token}).getManifest(n.project,n.stage),s=n.resources.filter((i)=>i.kind==="agent").map((i)=>({name:i.name,config:i.config??{},agentId:r?.ids.agents[i.name]}));return{manifest:n,agents:s}}async function Ds(e){let{manifest:n,agents:t}=await Pt(e);if(t.length===0){console.log(`No agents declared in ${n.project}/${n.stage}.`);return}console.log(`Agents in ${n.project}/${n.stage}:`);for(let o of t){let r=It(o.config),s=o.config.publicAccess===!0?"public":"private",i=o.agentId?o.agentId:"not deployed";console.log(` ${o.name} [${s}] ${r} (${i})`)}}async function _s(e,n){if(!e)throw Error(`Missing agent name.
|
|
391
393
|
|
|
392
394
|
${L("agent")}`);let{manifest:t,agents:o}=await Pt(n),r=o.find((p)=>p.name===e);if(!r)throw Error(`Unknown local agent: ${e}`);let s=r.config,i=[s.sandboxes].flat().filter((p)=>typeof p==="string").map((p,m)=>m===0?`${p} (default)`:p),a=Array.isArray(s.workspaces)?s.workspaces.map((p)=>typeof p==="string"?p:p.name).filter(Boolean):[],c=ce(s.tools)?Object.keys(s.tools):[],d=ce(s.channels)?Object.keys(s.channels):[],l=ce(s.subagent)&&Array.isArray(s.subagent.allowed)?s.subagent.allowed.map((p)=>typeof p==="string"?p:p.name).filter(Boolean):[],u=ce(s.hooks)&&Array.isArray(s.hooks.webhooks)?s.hooks.webhooks.filter(ce):[];if(console.log(`Agent: ${r.name}`),console.log(` Project/Stage: ${t.project}/${t.stage}`),console.log(` Deployed id: ${r.agentId??"not deployed"}`),console.log(` Public access: ${s.publicAccess===!0?"public (SSE/WebSocket enabled)":"private (secured by default)"}`),console.log(` Model: ${It(s)}`),console.log(` Sandboxes: ${i.length>0?i.join(", "):"none"}`),console.log(` Workspaces: ${a.length>0?a.join(", "):"none"}`),console.log(` Tools: ${c.length>0?c.join(", "):"none"}`),console.log(` Subagents: ${l.length>0?l.join(", "):"none"}`),console.log(` Channels: ${d.length>0?d.join(", "):"none"}`),u.length>0)console.log(" Webhooks:"),u.forEach((p,m)=>{let y=Array.isArray(p.events)&&p.events.length>0?p.events.join(", "):"all events",k=p.enabled===!1?"disabled":"enabled";console.log(` [${m}] ${k} → ${p.url??"none"} (${y})`)})}function It(e){let n=ce(e.model)?e.model:{},t=typeof n.provider==="string"?n.provider:void 0,o=typeof n.modelId==="string"?n.modelId:void 0;if(t&&o)return`${t}/${o}`;return o??t??"unconfigured model"}async function Ts(e){let[n,...t]=se(e);if(!n)throw Error(`Missing agent name.
|
|
393
395
|
|
|
394
|
-
${L("run")}`);let o=t.join(" "),r=Boolean(process.stdin.isTTY&&process.stdout.isTTY);if(!r&&!o)throw Error("Usage: broods run <agent> <prompt>. Omit the prompt for an interactive session, which requires a TTY.");let{manifest:s,config:i}=await ee({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),a=await G(b(e,"--base-url")??i.baseUrl),c=s.resources.find((R)=>R.kind==="agent"&&R.name===n);if(!c)throw Error(`Unknown local agent: ${n}`);let l=(await new D({baseUrl:a.baseUrl,token:a.token}).getManifest(s.project,s.stage))?.ids.agents[n];if(!l)throw Error(`Agent ${n} is not synced yet. Run broods dev --once or broods deploy first.`);let u=await new D({baseUrl:a.baseUrl,token:a.token}).getRuntimeKey(s.project,s.stage).catch(()=>null);if(u?.apiKey)await he("BROODS_API_KEY",u.apiKey);if(c.config.publicAccess!==!0)x(`⚠ Agent "${n}" does not set publicAccess: true. The public endpoint is secured by default; if the deployed agent has not enabled it, this run will be refused.`);let p=new j({baseUrl:b(e,"--base-url")??process.env.BROODS_BASE_URL??process.env.BROODS_HOST??a.baseUrl,...u?.apiKey?{apiKey:u.apiKey}:{}}),m={kind:"agent",name:n,id:l,project:s.project,stage:s.stage,...u?.endpointId?{endpointId:u.endpointId}:{},...u?.projectSlug?{projectSlug:u.projectSlug}:{},...u?.stageSlug?{stageSlug:u.stageSlug}:{}},{runAgentTui:y,streamAgentText:k}=await import("../chunk-
|
|
396
|
+
${L("run")}`);let o=t.join(" "),r=Boolean(process.stdin.isTTY&&process.stdout.isTTY);if(!r&&!o)throw Error("Usage: broods run <agent> <prompt>. Omit the prompt for an interactive session, which requires a TTY.");let{manifest:s,config:i}=await ee({project:b(e,"--project"),stage:b(e,"--stage"),command:"dev"}),a=await G(b(e,"--base-url")??i.baseUrl),c=s.resources.find((R)=>R.kind==="agent"&&R.name===n);if(!c)throw Error(`Unknown local agent: ${n}`);let l=(await new D({baseUrl:a.baseUrl,token:a.token}).getManifest(s.project,s.stage))?.ids.agents[n];if(!l)throw Error(`Agent ${n} is not synced yet. Run broods dev --once or broods deploy first.`);let u=await new D({baseUrl:a.baseUrl,token:a.token}).getRuntimeKey(s.project,s.stage).catch(()=>null);if(u?.apiKey)await he("BROODS_API_KEY",u.apiKey);if(c.config.publicAccess!==!0)x(`⚠ Agent "${n}" does not set publicAccess: true. The public endpoint is secured by default; if the deployed agent has not enabled it, this run will be refused.`);let p=new j({baseUrl:b(e,"--base-url")??process.env.BROODS_BASE_URL??process.env.BROODS_HOST??a.baseUrl,...u?.apiKey?{apiKey:u.apiKey}:{}}),m={kind:"agent",name:n,id:l,project:s.project,stage:s.stage,...u?.endpointId?{endpointId:u.endpointId}:{},...u?.projectSlug?{projectSlug:u.projectSlug}:{},...u?.stageSlug?{stageSlug:u.stageSlug}:{}},{runAgentTui:y,streamAgentText:k}=await import("../chunk-f294wr3z.js");try{if(r){await y({client:p,agent:m,...o?{prompt:o}:{}});return}await k({client:p,agent:m,prompt:o})}catch(R){if((R instanceof Error?R.message:String(R)).includes("public_access_disabled"))throw Error(`Agent "${n}" is not publicly accessible (secured by default). Set publicAccess: true in its config and redeploy, or enable Public access in the dashboard.`);throw R}}async function Be(e,n,t){try{await V(e,n,{flag:t?"w":"wx"})}catch(o){if(o.code==="EEXIST")return;throw o}}async function Dt(){let e=A(process.cwd(),S,".gitignore"),n=await be(e),o=["_generated",".cache"].filter((s)=>!n.split(/\r?\n/).some((i)=>i.trim()===s));if(o.length===0)return;let r=n?n.trimEnd()+`
|
|
395
397
|
`+o.join(`
|
|
396
398
|
`)+`
|
|
397
399
|
`:o.join(`
|
package/dist/index.d.ts
CHANGED
|
@@ -351,6 +351,7 @@ interface AgentChannelsConfig {
|
|
|
351
351
|
discord?: AgentDiscordChannelConfig;
|
|
352
352
|
pancake?: AgentPancakeChannelConfig;
|
|
353
353
|
zalo?: AgentZaloChannelConfig;
|
|
354
|
+
matrix?: AgentMatrixChannelConfig;
|
|
354
355
|
[key: string]: unknown;
|
|
355
356
|
}
|
|
356
357
|
/**
|
|
@@ -426,6 +427,33 @@ interface AgentDiscordChannelConfig {
|
|
|
426
427
|
partition?: ChannelPartition;
|
|
427
428
|
[key: string]: unknown;
|
|
428
429
|
}
|
|
430
|
+
/**
|
|
431
|
+
* A Matrix account the agent speaks as. Matrix has no bot concept, so this is
|
|
432
|
+
* usually a person's own account: replies carry a per-message profile named
|
|
433
|
+
* `botName`, and `mentionText` decides what addresses the agent, because a
|
|
434
|
+
* mention of the account would also be a mention of its owner.
|
|
435
|
+
*/
|
|
436
|
+
interface AgentMatrixChannelConfig {
|
|
437
|
+
id?: string;
|
|
438
|
+
/** Homeserver base URL, e.g. `https://matrix.org`. */
|
|
439
|
+
apiUrl?: string;
|
|
440
|
+
/** Access token of the account; `apps/matrix-forwarder` syncs with it. */
|
|
441
|
+
botToken?: string;
|
|
442
|
+
/** Room ids. */
|
|
443
|
+
allowedChannelIds?: string[];
|
|
444
|
+
/** Matrix user ids, e.g. `@alice:matrix.org`. */
|
|
445
|
+
allowedUserIds?: string[];
|
|
446
|
+
/** Name replies are shown under. Unset, replies look like the account's own messages. */
|
|
447
|
+
botName?: string;
|
|
448
|
+
/**
|
|
449
|
+
* Text that addresses the agent, e.g. `@georgi-ai`. Unset, a mention of the
|
|
450
|
+
* account does. Other messages are stored as context either way.
|
|
451
|
+
*/
|
|
452
|
+
mentionText?: string;
|
|
453
|
+
trace?: "enabled" | "disabled";
|
|
454
|
+
partition?: ChannelPartition;
|
|
455
|
+
[key: string]: unknown;
|
|
456
|
+
}
|
|
429
457
|
interface AgentPancakeChannelConfig {
|
|
430
458
|
allowedChannelIds?: string[];
|
|
431
459
|
allowedUserIds?: string[];
|
|
@@ -691,6 +719,29 @@ interface DiscordSource {
|
|
|
691
719
|
userId?: string;
|
|
692
720
|
}
|
|
693
721
|
|
|
722
|
+
/**
|
|
723
|
+
* Matrix channel adapter.
|
|
724
|
+
*
|
|
725
|
+
* Matrix delivers nothing over a webhook, so `apps/matrix-forwarder` holds a
|
|
726
|
+
* `/sync` long-poll per account, decrypts what arrives and POSTs each room
|
|
727
|
+
* message here. The forwarder also holds the account's end-to-end encryption
|
|
728
|
+
* keys, which is why every event sent into a room goes back through it.
|
|
729
|
+
* Media never does: an attachment's key rides the decrypted event, so this
|
|
730
|
+
* module downloads, decrypts, encrypts and uploads files against the
|
|
731
|
+
* homeserver itself.
|
|
732
|
+
*
|
|
733
|
+
* The wire shapes shared with the forwarder live in `matrix-wire.ts`.
|
|
734
|
+
*/
|
|
735
|
+
|
|
736
|
+
/** Where a reply goes: the room, and the thread when the message was in one. */
|
|
737
|
+
interface MatrixSource {
|
|
738
|
+
encrypted: boolean;
|
|
739
|
+
messageId: string;
|
|
740
|
+
roomId: string;
|
|
741
|
+
threadRootId?: string;
|
|
742
|
+
userId: string;
|
|
743
|
+
}
|
|
744
|
+
|
|
694
745
|
/**
|
|
695
746
|
* Pancake channel adapter.
|
|
696
747
|
*
|
|
@@ -1179,7 +1230,7 @@ interface AgentReference<Name extends string = string> {
|
|
|
1179
1230
|
}
|
|
1180
1231
|
interface ChannelReference {
|
|
1181
1232
|
readonly kind: "channel";
|
|
1182
|
-
readonly type: "telegram" | "github" | "slack" | "discord" | "pancake" | "zalo";
|
|
1233
|
+
readonly type: "telegram" | "github" | "slack" | "discord" | "matrix" | "pancake" | "zalo";
|
|
1183
1234
|
readonly agentName: string;
|
|
1184
1235
|
readonly agentId: string;
|
|
1185
1236
|
readonly accountId: string;
|
|
@@ -2033,7 +2084,7 @@ interface McpDefinitionConfig {
|
|
|
2033
2084
|
/** Tool names agents may use from this server; omit to allow all. */
|
|
2034
2085
|
allowedTools?: string[];
|
|
2035
2086
|
}
|
|
2036
|
-
type ChannelType = "telegram" | "github" | "slack" | "discord" | "pancake" | "zalo";
|
|
2087
|
+
type ChannelType = "telegram" | "github" | "slack" | "discord" | "matrix" | "pancake" | "zalo";
|
|
2037
2088
|
/**
|
|
2038
2089
|
* A connection is one app install: the credentials an agent needs before a
|
|
2039
2090
|
* provider can reach it at all. Channels point at a connection; a connection
|
|
@@ -2075,6 +2126,7 @@ type TelegramConnectionInput = EnvRefString<RequiredChannelKeys<Pick<AgentTelegr
|
|
|
2075
2126
|
type GitHubConnectionInput = EnvRefString<RequiredChannelKeys<Pick<AgentGitHubChannelConfig, "apiUrl" | "webhookSecret" | "appId" | "privateKey" | "botUserName" | "botUserId" | "triggerOnIssueOpen" | "triggerOnPROpen">, "webhookSecret" | "appId" | "privateKey">> & ConnectionIdentityInput;
|
|
2076
2127
|
type SlackConnectionInput = EnvRefString<RequiredChannelKeys<Pick<AgentSlackChannelConfig, "apiUrl" | "botToken" | "signingSecret" | "reactionEmoji">, "botToken" | "signingSecret">> & ConnectionIdentityInput;
|
|
2077
2128
|
type DiscordConnectionInput = EnvRefString<RequiredChannelKeys<Pick<AgentDiscordChannelConfig, "apiUrl" | "botToken" | "publicKey" | "botUserId" | "mentionRoleIds">, "botToken" | "publicKey">> & ConnectionIdentityInput;
|
|
2129
|
+
type MatrixConnectionInput = EnvRefString<RequiredChannelKeys<Pick<AgentMatrixChannelConfig, "apiUrl" | "botToken" | "botName" | "mentionText">, "apiUrl" | "botToken">> & ConnectionIdentityInput;
|
|
2078
2130
|
interface PancakeConnectionInput extends ConnectionIdentityInput {
|
|
2079
2131
|
pageId: ChannelSecret;
|
|
2080
2132
|
pageAccessToken: ChannelSecret;
|
|
@@ -2089,9 +2141,10 @@ type TelegramConnectionDefinition = ConnectionDefinition<"telegram", TelegramCon
|
|
|
2089
2141
|
type GitHubConnectionDefinition = ConnectionDefinition<"github", GitHubConnectionInput>;
|
|
2090
2142
|
type SlackConnectionDefinition = ConnectionDefinition<"slack", SlackConnectionInput>;
|
|
2091
2143
|
type DiscordConnectionDefinition = ConnectionDefinition<"discord", DiscordConnectionInput>;
|
|
2144
|
+
type MatrixConnectionDefinition = ConnectionDefinition<"matrix", MatrixConnectionInput>;
|
|
2092
2145
|
type PancakeConnectionDefinition = ConnectionDefinition<"pancake", PancakeConnectionInput>;
|
|
2093
2146
|
type ZaloConnectionDefinition = ConnectionDefinition<"zalo", ZaloConnectionInput>;
|
|
2094
|
-
type AnyConnectionDefinition = TelegramConnectionDefinition | GitHubConnectionDefinition | SlackConnectionDefinition | DiscordConnectionDefinition | PancakeConnectionDefinition | ZaloConnectionDefinition;
|
|
2147
|
+
type AnyConnectionDefinition = TelegramConnectionDefinition | GitHubConnectionDefinition | SlackConnectionDefinition | DiscordConnectionDefinition | MatrixConnectionDefinition | PancakeConnectionDefinition | ZaloConnectionDefinition;
|
|
2095
2148
|
/**
|
|
2096
2149
|
* One real place a team talks: a Slack channel, a Discord channel, a repo. It
|
|
2097
2150
|
* narrows and adds, and never grants what a bound agent lacks: instructions
|
|
@@ -2143,6 +2196,11 @@ type DiscordChannelInput = ChannelRulesInput & {
|
|
|
2143
2196
|
/** Guild the channel sits in. */
|
|
2144
2197
|
guildId?: string;
|
|
2145
2198
|
};
|
|
2199
|
+
type MatrixChannelInput = ChannelRulesInput & {
|
|
2200
|
+
connection: MatrixConnectionDefinition;
|
|
2201
|
+
/** Matrix room id, e.g. "!abc123:matrix.org". */
|
|
2202
|
+
channelId: string;
|
|
2203
|
+
};
|
|
2146
2204
|
type GitHubChannelInput = ChannelRulesInput & {
|
|
2147
2205
|
connection: GitHubConnectionDefinition;
|
|
2148
2206
|
/** Repository full name, e.g. "beeblast/api". */
|
|
@@ -2208,6 +2266,7 @@ type TelegramMessageSource = TelegramSource;
|
|
|
2208
2266
|
type GitHubMessageSource = GitHubSource;
|
|
2209
2267
|
type SlackMessageSource = SlackSource;
|
|
2210
2268
|
type DiscordMessageSource = DiscordSource;
|
|
2269
|
+
type MatrixMessageSource = MatrixSource;
|
|
2211
2270
|
type PancakeMessageSource = PancakeSource;
|
|
2212
2271
|
type ZaloMessageSource = ZaloSource;
|
|
2213
2272
|
/**
|
|
@@ -2230,6 +2289,10 @@ type ChannelMessageReceived = {
|
|
|
2230
2289
|
channel: "discord";
|
|
2231
2290
|
text: string;
|
|
2232
2291
|
source: DiscordMessageSource;
|
|
2292
|
+
} | {
|
|
2293
|
+
channel: "matrix";
|
|
2294
|
+
text: string;
|
|
2295
|
+
source: MatrixMessageSource;
|
|
2233
2296
|
} | {
|
|
2234
2297
|
channel: "pancake";
|
|
2235
2298
|
text: string;
|
|
@@ -2417,12 +2480,14 @@ declare function defineSkill<const Name extends string>(input: ResourceInput<Nam
|
|
|
2417
2480
|
declare function defineWorkspace<const Name extends string>(input: ResourceInput<Name, WorkspaceDefinitionConfig>): WorkspaceResource<Name>;
|
|
2418
2481
|
declare function defineDiscordConnection(config: DiscordConnectionInput): DiscordConnectionDefinition;
|
|
2419
2482
|
declare function defineGitHubConnection(config: GitHubConnectionInput): GitHubConnectionDefinition;
|
|
2483
|
+
declare function defineMatrixConnection(config: MatrixConnectionInput): MatrixConnectionDefinition;
|
|
2420
2484
|
declare function definePancakeConnection(config: PancakeConnectionInput): PancakeConnectionDefinition;
|
|
2421
2485
|
declare function defineSlackConnection(config: SlackConnectionInput): SlackConnectionDefinition;
|
|
2422
2486
|
declare function defineTelegramConnection(config: TelegramConnectionInput): TelegramConnectionDefinition;
|
|
2423
2487
|
declare function defineZaloConnection(config: ZaloConnectionInput): ZaloConnectionDefinition;
|
|
2424
2488
|
declare function defineDiscordChannel<const Name extends string>(input: ResourceInput<Name, DiscordChannelInput>): ChannelResource<Name>;
|
|
2425
2489
|
declare function defineGitHubChannel<const Name extends string>(input: ResourceInput<Name, GitHubChannelInput>): ChannelResource<Name>;
|
|
2490
|
+
declare function defineMatrixChannel<const Name extends string>(input: ResourceInput<Name, MatrixChannelInput>): ChannelResource<Name>;
|
|
2426
2491
|
declare function definePancakeChannel<const Name extends string>(input: ResourceInput<Name, PancakeChannelInput>): ChannelResource<Name>;
|
|
2427
2492
|
declare function defineSlackChannel<const Name extends string>(input: ResourceInput<Name, SlackChannelInput>): ChannelResource<Name>;
|
|
2428
2493
|
declare function defineTelegramChannel<const Name extends string>(input: ResourceInput<Name, TelegramChannelInput>): ChannelResource<Name>;
|
|
@@ -2431,5 +2496,5 @@ declare function isBroodsConfig(value: unknown): value is BroodsConfigDefinition
|
|
|
2431
2496
|
declare function isConnectionDefinition(value: unknown): value is AnyConnectionDefinition;
|
|
2432
2497
|
declare function isResource(value: unknown): value is AnyResource;
|
|
2433
2498
|
|
|
2434
|
-
export { BroodsAccountApiError, BroodsAccountClient, BroodsClient, BroodsWebSocketClient, DEFAULT_CORE_BASE_URL, IngressAcceptedError, MAX_OBSERVABILITY_BACKFILL, BroodsWebSocketClient as WebSocketClient, BroodsWebSocketClient as WebsocketClient, defineAgent, defineBroods, defineCron, defineDiscordChannel, defineDiscordConnection, defineGitHubChannel, defineGitHubConnection, defineHarness, defineMcp, definePancakeChannel, definePancakeConnection, definePolicy, defineSandbox, defineSkill, defineSlackChannel, defineSlackConnection, defineTelegramChannel, defineTelegramConnection, defineWorkspace, defineZaloChannel, defineZaloConnection, env, envPlaceholder, isBroodsConfig, isConnectionDefinition, isLogLevel, isObservabilityClientMessage, isResource, isRootSpanKind, isSandboxLogId, isTraceId, normalizeHttpServiceUrl, readSseStream, resolveEnvCredential, resolveRunEvents, toWebSocketBaseUrl, webSocketSubprotocols };
|
|
2435
|
-
export type { Account, AccountAgent, AccountChannel, AccountEnvVar, AccountMcp, AccountPolicy, AccountRole, AccountSandbox, AccountWorkspace, Agent, AgentChannelsConfig, AgentCodeHookConfig, AgentConfig, AgentConfigDoc, AgentContinueInput, AgentDefinitionConfig, AgentDiscordChannelConfig, AgentGitHubChannelConfig, AgentHandle, AgentHookEventName, AgentHooks, AgentHooksConfig, AgentPancakeChannelConfig, AgentProviderSettings, AgentReference, AgentResource, AgentRunAnswerInput, AgentRunEventInput, AgentRunInput, AgentRunModelOverrides, AgentRunOverrides, AgentRunResult, AgentSkillsDefinitionConfig, AgentSlackChannelConfig, AgentStreamPart, AgentSubagentDefinitionConfig, AgentTelegramChannelConfig, AgentWebhookHookConfig, AgentWorkspaceInput, AgentWorkspaceRef, AgentWorkspaceRefInput, AgentZaloChannelConfig, AnyConnectionDefinition, AnyResource, AssumeRoleResult, AsyncAgentRun, AsyncPollOptions, AsyncRequestAccepted, AsyncStatus, BroodsAccount, BroodsAccountClientOptions, BroodsClientOptions, BroodsConfigDefinition, BroodsProjectConfig, BroodsWebSocketClientOptions, ChannelAgentInput, ChannelDefinitionConfig, ChannelMessageReceived, ChannelPartition, ChannelRecordConfig, ChannelReference, ChannelReplyIn, ChannelResource, ChannelType, CliManifest, CliManifestResource, ConnectionDefinition, CreateAgentResult, CreateClientCronInput, CreateCronInput, CreateMcpInput, Cron, CronDefinitionConfig, CronDoc, CronLastStatus, CronResource, CronRun, CronStatus, DeleteAccountResult, DiscordChannelInput, DiscordConnectionDefinition, DiscordConnectionInput, DiscordMessageSource, DiscordSource, Doc, EnvAccessor, EnvRef, EnvRefString, GeneratedIds, GitHubChannelInput, GitHubConnectionDefinition, GitHubConnectionInput, GitHubMessageSource, GitHubSource, HarnessDefinition, HarnessType, HookContext, Id, IngressMode, IngressStatus, LogLevel, McpDefinitionConfig, McpHandler, McpOauthInput, McpResource, ObservabilityBackfillMessage, ObservabilityClientMessage, ObservabilityErrorMessage, ObservabilityFetchTraceMessage, ObservabilityLogEntry, ObservabilityLogMessage, ObservabilityReadyMessage, ObservabilityServerMessage, ObservabilitySpanMessage, ObservabilitySpanRow, ObservabilitySubscribeMessage, ObservabilityUnsubscribeMessage, PancakeChannelInput, PancakeConnectionDefinition, PancakeConnectionInput, PancakeMessageSource, PancakeSource, PendingQuestion, PolicyDefinitionConfig, PolicyDocument, PolicyResource, ProjectDoc, ProviderConfigInput, ProviderSettingsInput, QuestionAnswer, ResourceApi, ResourceDefinition, ResourceInput, ResourceKind, RotateSecretResult, Sandbox, SandboxConfig, SandboxConfigDoc, SandboxDefinitionConfig, SandboxDefinitionOptions, SandboxLifecycleResult, SandboxResource, SandboxSnapshotResult, SandboxTerminalTicket, Skill, SkillDefinitionConfig, SkillResource, SkillUploadInput, SlackChannelInput, SlackConnectionDefinition, SlackConnectionInput, SlackMessageSource, SlackSource, StageDoc, StageScope, TelegramChannelInput, TelegramConnectionDefinition, TelegramConnectionInput, TelegramMessageSource, TelegramSource, ToolApprovalSummary, UpdateAgentInput, UpdateCronInput, UpdateMcpInput, WebSocketAttachInput, WebSocketClientAttachMessage, WebSocketClientCancelMessage, WebSocketClientControlMessage, WebSocketClientExecuteMessage, WebSocketClientMessage, WebSocketConstructorLike, WebSocketHandlers, WebSocketLike, WebSocketOutputMessage, WebSocketRunInput, WebSocketServerMessage, WebSocketStreamMessage, WebSocketSubscription, Workspace, WorkspaceConfig, WorkspaceConfigDoc, WorkspaceDefinitionConfig, WorkspaceFileEntry, WorkspaceResource, ZaloChannelInput, ZaloConnectionDefinition, ZaloConnectionInput, ZaloMessageSource, ZaloSource };
|
|
2499
|
+
export { BroodsAccountApiError, BroodsAccountClient, BroodsClient, BroodsWebSocketClient, DEFAULT_CORE_BASE_URL, IngressAcceptedError, MAX_OBSERVABILITY_BACKFILL, BroodsWebSocketClient as WebSocketClient, BroodsWebSocketClient as WebsocketClient, defineAgent, defineBroods, defineCron, defineDiscordChannel, defineDiscordConnection, defineGitHubChannel, defineGitHubConnection, defineHarness, defineMatrixChannel, defineMatrixConnection, defineMcp, definePancakeChannel, definePancakeConnection, definePolicy, defineSandbox, defineSkill, defineSlackChannel, defineSlackConnection, defineTelegramChannel, defineTelegramConnection, defineWorkspace, defineZaloChannel, defineZaloConnection, env, envPlaceholder, isBroodsConfig, isConnectionDefinition, isLogLevel, isObservabilityClientMessage, isResource, isRootSpanKind, isSandboxLogId, isTraceId, normalizeHttpServiceUrl, readSseStream, resolveEnvCredential, resolveRunEvents, toWebSocketBaseUrl, webSocketSubprotocols };
|
|
2500
|
+
export type { Account, AccountAgent, AccountChannel, AccountEnvVar, AccountMcp, AccountPolicy, AccountRole, AccountSandbox, AccountWorkspace, Agent, AgentChannelsConfig, AgentCodeHookConfig, AgentConfig, AgentConfigDoc, AgentContinueInput, AgentDefinitionConfig, AgentDiscordChannelConfig, AgentGitHubChannelConfig, AgentHandle, AgentHookEventName, AgentHooks, AgentHooksConfig, AgentMatrixChannelConfig, AgentPancakeChannelConfig, AgentProviderSettings, AgentReference, AgentResource, AgentRunAnswerInput, AgentRunEventInput, AgentRunInput, AgentRunModelOverrides, AgentRunOverrides, AgentRunResult, AgentSkillsDefinitionConfig, AgentSlackChannelConfig, AgentStreamPart, AgentSubagentDefinitionConfig, AgentTelegramChannelConfig, AgentWebhookHookConfig, AgentWorkspaceInput, AgentWorkspaceRef, AgentWorkspaceRefInput, AgentZaloChannelConfig, AnyConnectionDefinition, AnyResource, AssumeRoleResult, AsyncAgentRun, AsyncPollOptions, AsyncRequestAccepted, AsyncStatus, BroodsAccount, BroodsAccountClientOptions, BroodsClientOptions, BroodsConfigDefinition, BroodsProjectConfig, BroodsWebSocketClientOptions, ChannelAgentInput, ChannelDefinitionConfig, ChannelMessageReceived, ChannelPartition, ChannelRecordConfig, ChannelReference, ChannelReplyIn, ChannelResource, ChannelType, CliManifest, CliManifestResource, ConnectionDefinition, CreateAgentResult, CreateClientCronInput, CreateCronInput, CreateMcpInput, Cron, CronDefinitionConfig, CronDoc, CronLastStatus, CronResource, CronRun, CronStatus, DeleteAccountResult, DiscordChannelInput, DiscordConnectionDefinition, DiscordConnectionInput, DiscordMessageSource, DiscordSource, Doc, EnvAccessor, EnvRef, EnvRefString, GeneratedIds, GitHubChannelInput, GitHubConnectionDefinition, GitHubConnectionInput, GitHubMessageSource, GitHubSource, HarnessDefinition, HarnessType, HookContext, Id, IngressMode, IngressStatus, LogLevel, MatrixChannelInput, MatrixConnectionDefinition, MatrixConnectionInput, MatrixMessageSource, MatrixSource, McpDefinitionConfig, McpHandler, McpOauthInput, McpResource, ObservabilityBackfillMessage, ObservabilityClientMessage, ObservabilityErrorMessage, ObservabilityFetchTraceMessage, ObservabilityLogEntry, ObservabilityLogMessage, ObservabilityReadyMessage, ObservabilityServerMessage, ObservabilitySpanMessage, ObservabilitySpanRow, ObservabilitySubscribeMessage, ObservabilityUnsubscribeMessage, PancakeChannelInput, PancakeConnectionDefinition, PancakeConnectionInput, PancakeMessageSource, PancakeSource, PendingQuestion, PolicyDefinitionConfig, PolicyDocument, PolicyResource, ProjectDoc, ProviderConfigInput, ProviderSettingsInput, QuestionAnswer, ResourceApi, ResourceDefinition, ResourceInput, ResourceKind, RotateSecretResult, Sandbox, SandboxConfig, SandboxConfigDoc, SandboxDefinitionConfig, SandboxDefinitionOptions, SandboxLifecycleResult, SandboxResource, SandboxSnapshotResult, SandboxTerminalTicket, Skill, SkillDefinitionConfig, SkillResource, SkillUploadInput, SlackChannelInput, SlackConnectionDefinition, SlackConnectionInput, SlackMessageSource, SlackSource, StageDoc, StageScope, TelegramChannelInput, TelegramConnectionDefinition, TelegramConnectionInput, TelegramMessageSource, TelegramSource, ToolApprovalSummary, UpdateAgentInput, UpdateCronInput, UpdateMcpInput, WebSocketAttachInput, WebSocketClientAttachMessage, WebSocketClientCancelMessage, WebSocketClientControlMessage, WebSocketClientExecuteMessage, WebSocketClientMessage, WebSocketConstructorLike, WebSocketHandlers, WebSocketLike, WebSocketOutputMessage, WebSocketRunInput, WebSocketServerMessage, WebSocketStreamMessage, WebSocketSubscription, Workspace, WorkspaceConfig, WorkspaceConfigDoc, WorkspaceDefinitionConfig, WorkspaceFileEntry, WorkspaceResource, ZaloChannelInput, ZaloConnectionDefinition, ZaloConnectionInput, ZaloMessageSource, ZaloSource };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{B,me,xe,Ce,Oe,Ae,F,ze,z,he,j,V,Pe,K,E,Me,Ne,je,qe,Le,De,Ue,Be,Fe,Ze,He,Ve,Ke,We,Ge,Je,Ye,Xe,Qe,et,tt,nt,ne,w,g}from"./chunk-
|
|
1
|
+
import{B,me,xe,Ce,Oe,Ae,F,ze,z,he,j,V,Pe,K,E,Me,Ne,je,qe,Le,De,Ue,Be,Fe,Ze,He,Ve,Ke,We,Ge,Je,Ye,Xe,Qe,et,tt,nt,rt,ot,ne,w,g}from"./chunk-9ex5d29v.js";import{m,Te,L,D}from"./chunk-9m85p3e3.js";export{m as BroodsAccountApiError,D as BroodsAccountClient,j as BroodsClient,Pe as BroodsWebSocketClient,z as DEFAULT_CORE_BASE_URL,he as IngressAcceptedError,xe as MAX_OBSERVABILITY_BACKFILL,Pe as WebSocketClient,Pe as WebsocketClient,Ne as defineAgent,je as defineBroods,qe as defineCron,Xe as defineDiscordChannel,He as defineDiscordConnection,Qe as defineGitHubChannel,Ve as defineGitHubConnection,Le as defineHarness,et as defineMatrixChannel,Ke as defineMatrixConnection,De as defineMcp,tt as definePancakeChannel,We as definePancakeConnection,Ue as definePolicy,Be as defineSandbox,Fe as defineSkill,nt as defineSlackChannel,Ge as defineSlackConnection,rt as defineTelegramChannel,Je as defineTelegramConnection,Ze as defineWorkspace,ot as defineZaloChannel,Ye as defineZaloConnection,Me as env,Te as envPlaceholder,ne as isBroodsConfig,w as isConnectionDefinition,Ce as isLogLevel,Oe as isObservabilityClientMessage,g as isResource,Ae as isRootSpanKind,F as isSandboxLogId,ze as isTraceId,V as normalizeHttpServiceUrl,me as readSseStream,L as resolveEnvCredential,B as resolveRunEvents,K as toWebSocketBaseUrl,E as webSocketSubprotocols};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "broods",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.1",
|
|
4
4
|
"description": "CLI + TypeScript SDK for the broods agent platform.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"esbuild": "^0.28.2"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
|
-
"@ai-sdk/tui": "1.0.
|
|
61
|
+
"@ai-sdk/tui": "1.0.108",
|
|
62
62
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
63
63
|
"@chat-adapter/discord": "^4.38.1",
|
|
64
64
|
"@chat-adapter/github": "^4.38.1",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"@modelcontextprotocol/server": "2.0.0",
|
|
68
68
|
"@types/bun": "^1.3.14",
|
|
69
69
|
"@typescript/typescript6": "6.0.2",
|
|
70
|
-
"ai": "^7.0.
|
|
70
|
+
"ai": "^7.0.107",
|
|
71
71
|
"publint": "^0.3.23",
|
|
72
72
|
"rollup": "^4.62.4",
|
|
73
73
|
"rollup-plugin-dts": "^6.5.1",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"zod": "^4.4.3"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
78
|
-
"ai": "^7.0.
|
|
78
|
+
"ai": "^7.0.107"
|
|
79
79
|
},
|
|
80
80
|
"engines": {
|
|
81
81
|
"node": ">=22.15"
|
|
File without changes
|