broods 0.9.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account.d.ts +10 -0
- package/dist/chunk-rr4srzb6.js +5 -0
- package/dist/cli/index.js +203 -102
- package/dist/index.d.ts +21 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-485rxfy0.js +0 -5
package/dist/index.d.ts
CHANGED
|
@@ -82,6 +82,7 @@ interface AgentConfig {
|
|
|
82
82
|
denyTools?: string[];
|
|
83
83
|
skills?: AgentSkillsConfig;
|
|
84
84
|
subagent?: AgentSubagentConfig;
|
|
85
|
+
scheduler?: AgentSchedulerConfig;
|
|
85
86
|
policy?: AgentPolicyConfig;
|
|
86
87
|
publicAccess?: boolean;
|
|
87
88
|
[key: string]: unknown;
|
|
@@ -112,6 +113,14 @@ interface AgentSkillsConfig {
|
|
|
112
113
|
allowed?: string[];
|
|
113
114
|
[key: string]: unknown;
|
|
114
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Opt-in for the `schedule` tool. Off by default: a scheduled task starts
|
|
118
|
+
* billable agent runs long after the turn that asked for it.
|
|
119
|
+
*/
|
|
120
|
+
interface AgentSchedulerConfig {
|
|
121
|
+
enabled?: boolean;
|
|
122
|
+
[key: string]: unknown;
|
|
123
|
+
}
|
|
115
124
|
interface AgentSubagentConfig {
|
|
116
125
|
enabled?: boolean;
|
|
117
126
|
allowed?: string[];
|
|
@@ -325,6 +334,7 @@ interface AgentZaloChannelConfig {
|
|
|
325
334
|
botToken?: string;
|
|
326
335
|
webhookSecret?: string;
|
|
327
336
|
allowedUserIds?: string[];
|
|
337
|
+
allowedGroupIds?: string[];
|
|
328
338
|
trace?: "enabled" | "disabled";
|
|
329
339
|
workspaceScope?: AgentChannelWorkspaceScope;
|
|
330
340
|
[key: string]: unknown;
|
|
@@ -473,6 +483,7 @@ interface WorkspaceConfig {
|
|
|
473
483
|
interface TelegramSource {
|
|
474
484
|
chatId: number;
|
|
475
485
|
messageId: string;
|
|
486
|
+
messageThreadId?: number;
|
|
476
487
|
threadId: string;
|
|
477
488
|
fromUserId?: number;
|
|
478
489
|
fromUsername?: string;
|
|
@@ -556,9 +567,11 @@ interface PancakeSource {
|
|
|
556
567
|
* Keep official Zalo Bot API webhook normalization and outbound API calls here.
|
|
557
568
|
*/
|
|
558
569
|
|
|
570
|
+
declare const ZALO_CHAT_TYPES: readonly ["PRIVATE", "GROUP"];
|
|
571
|
+
type ZaloChatType = (typeof ZALO_CHAT_TYPES)[number];
|
|
559
572
|
interface ZaloSource {
|
|
560
573
|
chatId: string;
|
|
561
|
-
chatType:
|
|
574
|
+
chatType: ZaloChatType;
|
|
562
575
|
messageId: string;
|
|
563
576
|
senderId: string;
|
|
564
577
|
senderName?: string;
|
|
@@ -1017,6 +1030,11 @@ declare class BroodsClient {
|
|
|
1017
1030
|
* to paste into the provider when several agents sit behind the same app.
|
|
1018
1031
|
*/
|
|
1019
1032
|
accountWebhookUrl(accountId: string, channelType: ChannelReference["type"]): string;
|
|
1033
|
+
/**
|
|
1034
|
+
* Return the provider webhook URL pinned to one stage. Production keeps the
|
|
1035
|
+
* bare account URL from `accountWebhookUrl`.
|
|
1036
|
+
*/
|
|
1037
|
+
stageWebhookUrl(accountId: string, endpointId: string, channelType: ChannelReference["type"]): string;
|
|
1020
1038
|
agent<const Name extends string>(ref: AgentReference<Name>): AgentHandle;
|
|
1021
1039
|
agent(name: string, agentId: string): AgentHandle;
|
|
1022
1040
|
/** Run an agent and accumulate the streamed text and raw parts. */
|
|
@@ -1714,6 +1732,7 @@ interface ZaloChannelInput extends ChannelIdentityInput {
|
|
|
1714
1732
|
botToken: ChannelSecret;
|
|
1715
1733
|
webhookSecret: ChannelSecret;
|
|
1716
1734
|
allowedUserIds?: readonly (string | EnvRef)[];
|
|
1735
|
+
allowedGroupIds?: readonly (string | EnvRef)[];
|
|
1717
1736
|
}
|
|
1718
1737
|
type TelegramChannelDefinition = ChannelDefinition<"telegram", TelegramChannelInput>;
|
|
1719
1738
|
type GitHubChannelDefinition = ChannelDefinition<"github", GitHubChannelInput>;
|
|
@@ -1904,7 +1923,7 @@ interface ProviderSettingsInput {
|
|
|
1904
1923
|
}
|
|
1905
1924
|
/** Per-provider settings; provider names stay synced with core's `AgentConfig`. */
|
|
1906
1925
|
type ProviderConfigInput = Partial<Record<keyof NonNullable<AgentConfig["provider"]>, ProviderSettingsInput>>;
|
|
1907
|
-
type AgentDefinitionConfig = EnvRefString<Pick<AgentConfig, "agent" | "model" | "session" | "tools">> & {
|
|
1926
|
+
type AgentDefinitionConfig = EnvRefString<Pick<AgentConfig, "agent" | "model" | "scheduler" | "session" | "tools">> & {
|
|
1908
1927
|
provider?: ProviderConfigInput;
|
|
1909
1928
|
} & {
|
|
1910
1929
|
harness?: HarnessDefinition;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as M,b as h,c as O}from"./chunk-ce3yb3yz.js";import{A as q,B as N,C as _,D as P,E as H,F as U,G as B,H as K,I as j,J as F,K as G,L as z,M as Z,N as V,O as X,d as x,e as I,p as v,q as k,r as S,s as A,t as R,u as W,v as L,w,x as E,y as D,z as T}from"./chunk-
|
|
1
|
+
import{a as M,b as h,c as O}from"./chunk-ce3yb3yz.js";import{A as q,B as N,C as _,D as P,E as H,F as U,G as B,H as K,I as j,J as F,K as G,L as z,M as Z,N as V,O as X,d as x,e as I,p as v,q as k,r as S,s as A,t as R,u as W,v as L,w,x as E,y as D,z as T}from"./chunk-rr4srzb6.js";import"./chunk-pfhy5049.js";var o=500;function a(s){if(typeof s!=="object"||s===null)return!1;let e=s;if(e.type==="subscribe"){let t=e.stream;if(t!=="logs"&&t!=="traces")return!1;let r=e.backfill;if(r!==void 0&&(typeof r!=="number"||!Number.isSafeInteger(r)||r<0||r>500))return!1;if(e.liveOnly!==void 0&&typeof e.liveOnly!=="boolean")return!1;let n=e.minLevel;if(n!==void 0&&n!=="INFO"&&n!=="WARN"&&n!=="ERROR")return!1;return!0}if(e.type==="unsubscribe"){let t=e.stream;return t==="logs"||t==="traces"}return!1}export{h as BroodsAccountApiError,O as BroodsAccountClient,S as BroodsClient,R as BroodsWebSocketClient,v as DEFAULT_CORE_BASE_URL,k as IngressAcceptedError,o as MAX_OBSERVABILITY_BACKFILL,R as WebSocketClient,R as WebsocketClient,P as defineAgent,_ as defineBroods,G as defineChannelRecord,z as defineCron,T as defineDiscordChannel,E as defineGitHubChannel,H as defineHarness,q as definePancakeChannel,F as definePolicy,B as defineSandbox,K as defineSkill,D as defineSlackChannel,w as defineTelegramChannel,j as defineTool,U as defineWorkspace,N as defineZaloChannel,L as env,M as envPlaceholder,X as isBroodsConfig,V as isChannelDefinition,a as isObservabilityClientMessage,Z as isResource,A as normalizeHttpServiceUrl,I as readSseStream,x as resolveRunEvents,W as toWebSocketBaseUrl};
|
package/package.json
CHANGED
package/dist/chunk-485rxfy0.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
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*E(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()}}import{mkdir as X,readFile as Q,writeFile as ee}from"node:fs/promises";import{homedir as ne}from"node:os";import{dirname as te,join as oe}from"node:path";var ve="broods",Ee="_generated",m=oe(ne(),".broods","config.json"),D="broods.app",T="dashboard",re="gateway";async function De(){let e=process.env.BROODS_TOKEN,n=process.env.BROODS_BASE_URL;if(e&&n)return{baseUrl:g(n),token:e,createdAt:new Date().toISOString()};try{let t=JSON.parse(await Q(m,"utf8"));if(typeof t.baseUrl!=="string"||!t.baseUrl)return null;return t}catch{return null}}async function Te(e){await X(te(m),{recursive:!0}),await ee(m,`${JSON.stringify(e,null,2)}
|
|
3
|
-
`,"utf8")}function P(){return process.env.BROODS_STAGE}function g(e){let n=e.length;while(n>0&&e.charCodeAt(n-1)===47)n-=1;return e.slice(0,n)}function Pe(e){try{let n=new URL(e);if(!n.hostname.startsWith(`${T}.`))return;let t=n.hostname.slice(T.length+1);if(t!==D&&!t.endsWith(`.${D}`))return;return n.hostname=`${re}.${t}`,g(n.origin)}catch{return}}import{existsSync as O,readFileSync as v,statSync as se}from"node:fs";import{join as U,resolve as W}from"node:path";var I=new Map,ie=new Set(Object.keys(process.env)),N=new Set;function k(e=process.cwd()){ae(e);let n=le();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:P()}}function Me(e,n=process.cwd()){let t=process.env[e];if(t===void 0)return!1;let o=W(n);for(let r of[".env.local",".env"]){let s=U(o,r);if(!O(s))continue;let i=M(v(s,"utf8"));if(i[e]!==void 0)return i[e]!==t}return!0}function ae(e){let n=W(e),t=process.env.BROODS_RELOAD_ENV==="1";for(let o of[".env",".env.local"]){let r=U(n,o);if(!O(r)){I.delete(r);continue}let s=se(r).mtimeMs,i=I.get(r);if(i&&i.mtimeMs===s)continue;I.set(r,{mtimeMs:s});for(let[a,l]of Object.entries(M(v(r,"utf8"))))if(t||!ie.has(a)||N.has(a))process.env[a]=l,N.add(a)}}function M(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]=ce(r.slice(s+1).trim())}return n}function ce(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 le(){try{let e=JSON.parse(v(m,"utf8"));if(typeof e.baseUrl!=="string"||typeof e.token!=="string")return null;return{baseUrl:g(e.baseUrl),...typeof e.dashboardUrl==="string"?{dashboardUrl:g(e.dashboardUrl)}:{},token:e.token}}catch{return null}}var A="https://gateway.broods.app";class H extends Error{accepted;constructor(e){super(`Ingress ${e.eventId} was accepted asynchronously with status ${e.status??"queued"}`);this.accepted=e;this.name="IngressAcceptedError"}}class ge{baseUrl;apiKey;fetchImpl;constructor(e={}){k(),this.baseUrl=w(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||A),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}/webhooks/${t.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}),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),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=_(t,"cli"),r=n?this.scopedUrl(e):this.baseUrl,s=await this.openStream(o,r);if(!s.ok)throw Error(`Run failed: ${s.status} ${await s.text()}`);if(s.status===202)throw new H(K(await s.json(),o));if(!s.body)throw Error("Run response has no body");for await(let i of E(s.body)){let a;try{a=JSON.parse(i)}catch{continue}if(a.type==="error")throw Error(`Agent run failed: ${me(a.error)}`);yield a}}async runAsync(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o=_(t,"async"),r=n?this.scopedUrl(e,"/async"):`${this.baseUrl}/async`,s=await this.fetchJson(r,{method:"POST",headers:this.apiKeyHeaders(),body:JSON.stringify(o)});if(s.status!==202)throw Error(`Async run failed: ${s.status} ${await pe(s,"202 JSON")}`);let i=K(await s.json(),o);return{...i,conversationKey:o.conversationKey,poll:()=>this.getAsyncStatus(i),wait:(a)=>this.waitForAsyncStatus(i,a)}}async getAsyncStatus(e,n={}){let t=this.resolveStatusUrl(e,n),o=await this.fetchJson(t,{method:"GET",headers:this.apiKeyHeaders()});if(o.status===404)return{status:"not_found"};if(!o.ok)throw Error(`Status check failed: ${o.status} ${await o.text()}`);return await o.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,n);if(r.status==="awaiting_approval"||r.status==="completed"||r.status==="failed"||r.status==="expired"||r.status==="not_found")return r;await ye(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(fe(e))});if(n.status!==201)throw Error(`Create cron job failed: ${n.status} ${await p(n)}`);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 p(e)}`);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 p(n)}`);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 p(r)}`);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 p(t)}`);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 p(n)}`);return(await n.json()).deleted}scopedUrl(e,n=""){if(e.projectSlug&&e.stageSlug&&e.endpointId)return`${this.baseUrl}/v1/${encodeURIComponent(e.projectSlug)}/agents/${encodeURIComponent(e.stageSlug)}/${encodeURIComponent(e.endpointId)}${n}`;return`${this.baseUrl}${n}`}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 ${A} 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,n){if(typeof e!=="string")return e.statusUrl;if(/^https?:\/\//.test(e))return e;if(!n.agentId)throw Error("Polling by status id requires agentId.");return de(this.baseUrl,e,n.agentId)}}function w(e){let n=e.trim(),t=/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(n)?n:`https://${n}`;return g(t)}function _(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 K(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=ue(t);if(!o.statusId)throw Error("Async response statusUrl missing status id");let r=typeof e.eventId==="string"?e.eventId:o.statusId,s=e.status,i=e.requestedMode;return{statusUrl:t,statusId:o.statusId,eventId:r,agentId:o.agentId??n.agentId,...s==="accepted"||s==="queued"||s==="applied"||s==="processing"?{status:s}:{},...i==="reject"||i==="followup"||i==="collect"||i==="steer"?{requestedMode:i}:{}}}function ue(e){let n=new URL(e),t=n.pathname.match(/\/status\/([^/]+)$/);return{statusId:t?.[1]?decodeURIComponent(t[1]):void 0,agentId:n.searchParams.get("agentId")??void 0}}function de(e,n,t){return`${w(e)}/status/${encodeURIComponent(n)}?agentId=${encodeURIComponent(t)}`}async function pe(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 routed /async to the direct streaming runner instead of the async handler.`;let o=await e.text();if(o.length<=2000)return o;return`${o.slice(0,2000)}... [truncated ${o.length-2000} chars]`}async function p(e){let n=await e.text();if(n.includes("Request body must include eventId and conversationKey"))return`${n}. Cron job APIs must be served by the configured baseUrl. Prefer defining stable cron jobs with defineCron(...) in broods/ and syncing with \`broods dev\` or \`broods deploy\`.`;return n}function fe(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}}function ye(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 me(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}`}var he=2000,B=0,h=1;class Se{baseUrl;apiKey;WebSocketImpl;connectTimeoutMs;constructor(e={}){if(k(),this.baseUrl=J(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||A),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??he}subscribe(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=Re(e),s=j(this.baseUrl),i=new t(o),a=!1,l=!1,u=setTimeout(()=>{if(!a)y(s)},this.connectTimeoutMs),x=(c=1000,R="client closed")=>{if(l)return;if(l=!0,clearTimeout(u),e.signal?.removeEventListener("abort",S),i.readyState===h||i.readyState===B)i.close(c,R)},y=(c)=>{n.onError?.(c),x(1011,"websocket error")},Y=()=>{n.onDone?.(),x(1000,"done")},S=()=>{if(i.readyState===h)i.send(JSON.stringify({type:"cancel"}));y(Error("WebSocket run aborted."))};return e.signal?.addEventListener("abort",S,{once:!0}),i.onopen=()=>{if(a=!0,clearTimeout(u),e.signal?.aborted){S();return}i.send(JSON.stringify({type:"execute",agentId:r,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 R=q(c.data);if(!R)return;let C=L(R,n);switch(n.onMessage?.(C),C.type){case"meta":n.onMeta?.(C);break;case"done":Y();break;case"error":y(Error(G(C.error)));break}},i.onerror=()=>{y(s)},i.onclose=(c)=>{if(clearTimeout(u),e.signal?.removeEventListener("abort",S),l||c.code===1000)return;y(Error(c.reason||"WebSocket connection closed."))},{url:o,sendControl:function(c){if(i.readyState!==h)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),s=!1,i=(a=1000,l="client closed")=>{if(s)return;if(s=!0,r.readyState===h||r.readyState===B)r.close(a,l)};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 l=q(a.data);if(!l)return;let u=L(l,n);if(n.onMessage?.(u),u.type==="done")n.onDone?.();if(u.type==="error")n.onError?.(Error(G(u.error)))},r.onerror=()=>n.onError?.(j(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!==h)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=Ce(e),t=e.projectSlug??e.agent?.projectSlug,o=e.stageSlug??e.agent?.stageSlug,r=t?`/${t}`:"",s=o?`/${o}`:"";return`${be(this.baseUrl)}/v1${r}/agents${s}/${encodeURIComponent(n)}/ws?token=${encodeURIComponent(this.apiKey)}`}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 Re(e){let n=e.agentId??e.agent?.id??e.endpointId;if(!n)throw Error("WebSocket run requires agent, agentId, or endpointId.");return n}function Ce(e){let n=e.endpointId??e.agent?.endpointId??e.agent?.id;if(!n)throw Error("WebSocket run requires agent or endpointId.");return n}function be(e){let n=new URL(J(e));if(n.protocol==="https:")n.protocol="wss:";if(n.protocol==="http:")n.protocol="ws:";return g(n.toString())}function J(e){let n=e.trim();if(/^wss?:\/\//.test(n))return g(n);return w(n)}function j(e){return Error(`Cannot access the WebSocket service at ${e}.`)}function L(e,n){if(e.type!=="output")return e;let t=e;return n.onOutput?.(t),t.data}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 G(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)}var Z=Symbol.for("broods.resource"),z=Symbol.for("broods.config"),V=Symbol.for("broods.channel"),F=/^[A-Z][A-Z0-9_]{0,63}$/;var Ze=new Proxy((e)=>{if(!F.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"&&F.test(n))throw Error(`env.${n} is not supported; use env("${n}")`);return Reflect.get(e,n,t)}});function d(e,n,t,o){return{[Z]:!0,kind:e,name:n,...t?{description:t}:{},config:o}}function f(e,n){let{workspaceScope:t,...o}=n;return{[V]:!0,kind:"channel",type:e,...t?{workspaceScope:t}:{},config:{...o,...t?{workspaceScope:t}:{}}}}function ze(e){return f("telegram",e)}function Ve(e){return f("github",e)}function Ye(e){return f("slack",e)}function Xe(e){return f("discord",e)}function Qe(e){return f("pancake",e)}function en(e){return f("zalo",e)}function nn(e){return{[z]:!0,config:e}}function tn(e){let{name:n,description:t,...o}=e;return d("agent",n,t,o)}function on(e){return e}function rn(e){let{name:n,description:t,...o}=e;return d("workspace",n,t,o)}function sn(e){let{name:n,description:t,...o}=e;return d("sandbox",n,t,o)}function an(e){let{name:n,description:t,...o}=e;return d("skill",n,t,o)}function cn(e){let{name:n,...t}=e;return d("tool",n,void 0,t)}function ln(e){let{name:n,description:t,...o}=e;return d("policy",n,t,o)}function gn(e){let{name:n,description:t,...o}=e;return d("channelRecord",n,t,o)}function un(e){let{name:n,description:t,...o}=e;return d("cron",n,t,o)}function dn(e){return Boolean(e&&typeof e==="object"&&e[Z])}function pn(e){return Boolean(e&&typeof e==="object"&&e[V])}function fn(e){return Boolean(e&&typeof e==="object"&&e[z])}
|
|
5
|
-
export{b as d,E as e,ve as f,Ee as g,m as h,De as i,Te as j,P as k,g as l,Pe as m,k as n,Me as o,A as p,H as q,ge as r,w as s,Se as t,be as u,Ze as v,ze as w,Ve as x,Ye as y,Xe as z,Qe as A,en as B,nn as C,tn as D,on as E,rn as F,sn as G,an as H,cn as I,ln as J,gn as K,un as L,dn as M,pn as N,fn as O};
|