broods 0.7.0 → 0.9.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/index.d.ts CHANGED
@@ -262,6 +262,7 @@ interface AgentTelegramChannelConfig {
262
262
  webhookSecret?: string;
263
263
  allowedChatIds?: number[];
264
264
  reactionEmoji?: string;
265
+ trace?: "enabled" | "disabled";
265
266
  workspaceScope?: AgentChannelWorkspaceScope;
266
267
  [key: string]: unknown;
267
268
  }
@@ -280,6 +281,7 @@ interface AgentGitHubChannelConfig {
280
281
  triggerOnIssueOpen?: boolean;
281
282
  /** When false, the bot does not auto-trigger on new PRs (opened/edited/reopened). Defaults to true. The bot still triggers when assigned to a PR. */
282
283
  triggerOnPROpen?: boolean;
284
+ trace?: "enabled" | "disabled";
283
285
  workspaceScope?: AgentChannelWorkspaceScope;
284
286
  [key: string]: unknown;
285
287
  }
@@ -290,6 +292,7 @@ interface AgentSlackChannelConfig {
290
292
  signingSecret?: string;
291
293
  allowedChannelIds?: string[];
292
294
  reactionEmoji?: string;
295
+ trace?: "enabled" | "disabled";
293
296
  workspaceScope?: AgentChannelWorkspaceScope;
294
297
  [key: string]: unknown;
295
298
  }
@@ -303,6 +306,7 @@ interface AgentDiscordChannelConfig {
303
306
  botUserId?: string;
304
307
  /** Role ids that count as mentioning the agent, e.g. an on-call role. */
305
308
  mentionRoleIds?: string[];
309
+ trace?: "enabled" | "disabled";
306
310
  workspaceScope?: AgentChannelWorkspaceScope;
307
311
  [key: string]: unknown;
308
312
  }
@@ -312,6 +316,7 @@ interface AgentPancakeChannelConfig {
312
316
  pageAccessToken?: string;
313
317
  webhookSecret?: string;
314
318
  senderId?: string;
319
+ trace?: "enabled" | "disabled";
315
320
  workspaceScope?: AgentChannelWorkspaceScope;
316
321
  [key: string]: unknown;
317
322
  }
@@ -320,6 +325,7 @@ interface AgentZaloChannelConfig {
320
325
  botToken?: string;
321
326
  webhookSecret?: string;
322
327
  allowedUserIds?: string[];
328
+ trace?: "enabled" | "disabled";
323
329
  workspaceScope?: AgentChannelWorkspaceScope;
324
330
  [key: string]: unknown;
325
331
  }
@@ -587,7 +593,7 @@ type GeneratedIds = {
587
593
  type CliManifest = {
588
594
  version: 1;
589
595
  project: string;
590
- environment: string;
596
+ stage: string;
591
597
  resources: CliManifestResource[];
592
598
  };
593
599
 
@@ -604,7 +610,7 @@ type Doc<TableName extends string = string> = Record<string, unknown> & {
604
610
  };
605
611
 
606
612
  type ProjectDoc = Doc<"projects">;
607
- type EnvironmentDoc = Doc<"environments">;
613
+ type StageDoc = Doc<"stages">;
608
614
  type AgentConfigDoc = Doc<"agentConfigs">;
609
615
  type WorkspaceConfigDoc = Doc<"workspaceConfigs">;
610
616
  type SandboxConfigDoc = Doc<"sandboxConfigs">;
@@ -948,16 +954,16 @@ interface AgentReference<Name extends string = string> {
948
954
  readonly name: Name;
949
955
  readonly id: string;
950
956
  readonly project: string;
951
- readonly environment: string;
957
+ readonly stage: string;
952
958
  /**
953
- * Authoritative scope of the environment's runtime key, embedded by codegen
959
+ * Authoritative scope of the stage's runtime key, embedded by codegen
954
960
  * from the deploy response. When present the client posts to the scoped URL
955
- * `/v1/{projectSlug}/agents/{environmentSlug}/{endpointId}` (matching the
961
+ * `/v1/{projectSlug}/agents/{stageSlug}/{endpointId}` (matching the
956
962
  * dashboard); when absent it falls back to the base URL.
957
963
  */
958
964
  readonly endpointId?: string;
959
965
  readonly projectSlug?: string;
960
- readonly environmentSlug?: string;
966
+ readonly stageSlug?: string;
961
967
  }
962
968
  interface ChannelReference {
963
969
  readonly kind: "channel";
@@ -1049,7 +1055,7 @@ declare class BroodsClient {
1049
1055
  deleteCron(cronId: string): Promise<boolean>;
1050
1056
  /**
1051
1057
  * Scoped invoke URL for a deployed agent. When codegen embedded the runtime
1052
- * key's scope, this is `/v1/{projectSlug}/agents/{environmentSlug}/{endpointId}`
1058
+ * key's scope, this is `/v1/{projectSlug}/agents/{stageSlug}/{endpointId}`
1053
1059
  * (the same URL the dashboard shows, so core can validate the key against the
1054
1060
  * path); otherwise it falls back to the base URL.
1055
1061
  */
@@ -1221,17 +1227,17 @@ interface ChannelRecordConfig {
1221
1227
  actorIds: string[];
1222
1228
  }>;
1223
1229
  }
1224
- /** The environment a tool belongs to. Tools with the same name in two environments are two tools. */
1230
+ /** The stage a tool belongs to. Tools with the same name in two stages are two tools. */
1225
1231
  interface ToolScope {
1226
1232
  project: string;
1227
- environment: string;
1233
+ stage: string;
1228
1234
  }
1229
1235
  /** Public uploaded-tool record returned by the tools routes. */
1230
1236
  interface AccountTool {
1231
1237
  accountId: string;
1232
1238
  toolId: string;
1233
1239
  projectId: string;
1234
- environmentId: string;
1240
+ stageId: string;
1235
1241
  name: string;
1236
1242
  description: string;
1237
1243
  inputSchema: unknown;
@@ -1416,7 +1422,7 @@ declare class BroodsAccountClient {
1416
1422
  snapshotSandbox(sandboxId: string, reservationKey: string, name: string): Promise<SandboxSnapshotResult>;
1417
1423
  /** Mint a short-lived sealed ticket for an interactive PTY session on a persistent sandbox (`sandbox`/`lambda` providers). Throws on 404/403/409. */
1418
1424
  openSandboxTerminal(sandboxId: string, reservationKey: string): Promise<SandboxTerminalTicket>;
1419
- /** Tools live in one environment, so the collection routes need a scope. Both fields are required. */
1425
+ /** Tools live in one stage, so the collection routes need a scope. Both fields are required. */
1420
1426
  listTools(scope: ToolScope): Promise<AccountTool[]>;
1421
1427
  createTool(scope: ToolScope, input: CreateToolInput): Promise<AccountTool>;
1422
1428
  getTool(toolId: string): Promise<AccountTool | null>;
@@ -1483,7 +1489,7 @@ type WebSocketRunInput = {
1483
1489
  sessionId?: string;
1484
1490
  eventId?: string;
1485
1491
  projectSlug?: string;
1486
- environmentSlug?: string;
1492
+ stageSlug?: string;
1487
1493
  signal?: AbortSignal;
1488
1494
  /** Defaults to "steer": join the live run at its next step boundary. */
1489
1495
  mode?: "reject" | "followup" | "collect" | "steer";
@@ -1493,7 +1499,7 @@ type WebSocketAttachInput = Omit<WebSocketClientAttachMessage, "type"> & {
1493
1499
  endpointId?: string;
1494
1500
  agent?: AgentReference;
1495
1501
  projectSlug?: string;
1496
- environmentSlug?: string;
1502
+ stageSlug?: string;
1497
1503
  signal?: AbortSignal;
1498
1504
  };
1499
1505
  interface WebSocketHandlers {
@@ -1553,7 +1559,7 @@ declare class BroodsWebSocketClient {
1553
1559
  /** Attach to a previously started event and replay from an exclusive cursor. */
1554
1560
  attach(input: WebSocketAttachInput, handlers?: WebSocketHandlers): WebSocketSubscription;
1555
1561
  stream(input: WebSocketRunInput): AsyncGenerator<WebSocketServerMessage>;
1556
- buildUrl(input: Pick<WebSocketRunInput, "agent" | "endpointId" | "projectSlug" | "environmentSlug">): string;
1562
+ buildUrl(input: Pick<WebSocketRunInput, "agent" | "endpointId" | "projectSlug" | "stageSlug">): string;
1557
1563
  private resolveWebSocket;
1558
1564
  }
1559
1565
 
@@ -1584,7 +1590,7 @@ type EnvRefString<T> = T extends string ? T | EnvRef : T extends readonly (infer
1584
1590
  } : T;
1585
1591
  interface BroodsProjectConfig {
1586
1592
  project?: string;
1587
- environments?: {
1593
+ stages?: {
1588
1594
  dev?: string;
1589
1595
  deploy?: string;
1590
1596
  [name: string]: string | undefined;
@@ -1670,9 +1676,10 @@ interface ToolDefinitionConfig<Input = Record<string, unknown>> {
1670
1676
  inputSchema: Record<string, unknown>;
1671
1677
  runtime?: "isolate" | "sandbox";
1672
1678
  /**
1673
- * Account-wide, non-secret defaults. Environment references are rejected
1674
- * here; put `env("NAME")` under the enabling agent's `tools.<tool>.config` so
1675
- * the value is resolved per environment and stored with encrypted agent config.
1679
+ * Account-wide, non-secret defaults. Environment variable references are
1680
+ * rejected here; put `env("NAME")` under the enabling agent's
1681
+ * `tools.<tool>.config` so the value is resolved per stage and stored with
1682
+ * encrypted agent config.
1676
1683
  */
1677
1684
  defaultConfig?: Record<string, unknown>;
1678
1685
  }
@@ -1690,6 +1697,7 @@ interface ChannelDefinition<Type extends ChannelType, Config> {
1690
1697
  type RequiredChannelKeys<Config, Keys extends keyof Config> = Required<Pick<Config, Keys>> & Omit<Config, Keys>;
1691
1698
  type ChannelSecret = string | EnvRef | undefined;
1692
1699
  type ChannelIdentityInput = {
1700
+ trace?: "enabled" | "disabled";
1693
1701
  workspaceScope?: AgentChannelWorkspaceScope;
1694
1702
  };
1695
1703
  type TelegramChannelInput = EnvRefString<RequiredChannelKeys<Pick<AgentTelegramChannelConfig, "apiUrl" | "botToken" | "webhookSecret" | "allowedChatIds" | "reactionEmoji">, "botToken" | "webhookSecret" | "allowedChatIds">> & ChannelIdentityInput;
@@ -1911,7 +1919,7 @@ type AgentDefinitionConfig = EnvRefString<Pick<AgentConfig, "agent" | "model" |
1911
1919
  policy?: AgentPolicyDefinitionConfig;
1912
1920
  /**
1913
1921
  * Opt the agent into the public runtime endpoint (SSE/WebSocket via the
1914
- * environment runtime key). Off by default — secured: when unset the public
1922
+ * stage runtime key). Off by default — secured: when unset the public
1915
1923
  * endpoint refuses requests for this agent. Reach a private agent through an
1916
1924
  * internal endpoint or a channel webhook. See issue #65.
1917
1925
  */
@@ -1995,4 +2003,4 @@ declare function isChannelDefinition(value: unknown): value is AnyChannelDefinit
1995
2003
  declare function isBroodsConfig(value: unknown): value is BroodsConfigDefinition;
1996
2004
 
1997
2005
  export { BroodsAccountApiError, BroodsAccountClient, BroodsClient, BroodsWebSocketClient, DEFAULT_CORE_BASE_URL, IngressAcceptedError, MAX_OBSERVABILITY_BACKFILL, BroodsWebSocketClient as WebSocketClient, BroodsWebSocketClient as WebsocketClient, defineAgent, defineBroods, defineChannelRecord, defineCron, defineDiscordChannel, defineGitHubChannel, defineHarness, definePancakeChannel, definePolicy, defineSandbox, defineSkill, defineSlackChannel, defineTelegramChannel, defineTool, defineWorkspace, defineZaloChannel, env, envPlaceholder, isBroodsConfig, isChannelDefinition, isObservabilityClientMessage, isResource, normalizeHttpServiceUrl, readSseStream, resolveRunEvents, toWebSocketBaseUrl };
1998
- export type { Account, AccountAgent, AccountChannel, AccountEnvVar, AccountPolicy, AccountSandbox, AccountTool, AccountWorkspace, Agent, AgentChannelWorkspaceScope, AgentChannelsConfig, AgentCodeHookConfig, AgentConfig, AgentConfigDoc, AgentDefinitionConfig, AgentDiscordChannelConfig, AgentGitHubChannelConfig, AgentHandle, AgentHookEventName, AgentHooks, AgentHooksConfig, AgentPancakeChannelConfig, AgentPolicyConfig, AgentPolicyDefinitionConfig, AgentPolicyDocument, AgentProviderSettings, AgentReference, AgentResource, AgentRunEventInput, AgentRunInput, AgentRunModelOverrides, AgentRunOverrides, AgentRunResult, AgentSkillsDefinitionConfig, AgentSlackChannelConfig, AgentStreamPart, AgentSubagentDefinitionConfig, AgentTelegramChannelConfig, AgentWebhookHookConfig, AgentWorkspaceInput, AgentWorkspaceRef, AgentWorkspaceRefInput, AgentZaloChannelConfig, AnyChannelDefinition, AnyResource, AsyncAgentRun, AsyncPollOptions, AsyncRequestAccepted, AsyncStatus, BroodsAccount, BroodsAccountClientOptions, BroodsClientOptions, BroodsConfigDefinition, BroodsProjectConfig, BroodsWebSocketClientOptions, ChannelDefinition, ChannelMessageReceived, ChannelRecordConfig, ChannelRecordDefinitionConfig, ChannelRecordResource, ChannelReference, ChannelType, CliManifest, CliManifestResource, CliResourceKind, CreateAgentResult, CreateClientCronInput, CreateCronInput, CreateToolInput, Cron, CronDefinitionConfig, CronDoc, CronLastStatus, CronResource, CronRun, CronStatus, CustomTool, DeleteAccountResult, DiscordChannelDefinition, DiscordChannelInput, DiscordMessageSource, DiscordSource, Doc, EnvAccessor, EnvRef, EnvRefString, EnvironmentDoc, GeneratedIds, GitHubChannelDefinition, GitHubChannelInput, GitHubMessageSource, GitHubSource, HarnessDefinition, HarnessType, HookContext, Id, IngressMode, IngressStatus, LogLevel, ObservabilityBackfillMessage, ObservabilityClientMessage, ObservabilityErrorMessage, ObservabilityLogEntry, ObservabilityLogMessage, ObservabilityReadyMessage, ObservabilityServerMessage, ObservabilitySpanMessage, ObservabilitySpanRow, ObservabilitySubscribeMessage, ObservabilityUnsubscribeMessage, PancakeChannelDefinition, PancakeChannelInput, PancakeMessageSource, PancakeSource, PolicyDefinitionConfig, PolicyResource, ProjectDoc, ProviderConfigInput, ProviderSettingsInput, ResourceApi, ResourceDefinition, ResourceInput, ResourceKind, RotateSecretResult, Sandbox, SandboxConfig, SandboxConfigDoc, SandboxDefinitionConfig, SandboxLifecycleResult, SandboxResource, SandboxSnapshotResult, SandboxTerminalTicket, Skill, SkillDefinitionConfig, SkillResource, SkillUploadInput, SlackChannelDefinition, SlackChannelInput, SlackMessageSource, SlackSource, TelegramChannelDefinition, TelegramChannelInput, TelegramMessageSource, TelegramSource, ToolApprovalSummary, ToolDefinitionConfig, ToolExecuteContext, ToolExecuteOptions, ToolResource, ToolScope, UpdateAgentInput, UpdateCronInput, UpdateToolInput, WebSocketAttachInput, WebSocketClientAttachMessage, WebSocketClientCancelMessage, WebSocketClientControlMessage, WebSocketClientExecuteMessage, WebSocketClientMessage, WebSocketConstructorLike, WebSocketHandlers, WebSocketLike, WebSocketOutputMessage, WebSocketRunInput, WebSocketServerMessage, WebSocketStreamMessage, WebSocketSubscription, Workspace, WorkspaceConfig, WorkspaceConfigDoc, WorkspaceFileEntry, WorkspaceResource, ZaloChannelDefinition, ZaloChannelInput, ZaloMessageSource, ZaloSource };
2006
+ export type { Account, AccountAgent, AccountChannel, AccountEnvVar, AccountPolicy, AccountSandbox, AccountTool, AccountWorkspace, Agent, AgentChannelWorkspaceScope, AgentChannelsConfig, AgentCodeHookConfig, AgentConfig, AgentConfigDoc, AgentDefinitionConfig, AgentDiscordChannelConfig, AgentGitHubChannelConfig, AgentHandle, AgentHookEventName, AgentHooks, AgentHooksConfig, AgentPancakeChannelConfig, AgentPolicyConfig, AgentPolicyDefinitionConfig, AgentPolicyDocument, AgentProviderSettings, AgentReference, AgentResource, AgentRunEventInput, AgentRunInput, AgentRunModelOverrides, AgentRunOverrides, AgentRunResult, AgentSkillsDefinitionConfig, AgentSlackChannelConfig, AgentStreamPart, AgentSubagentDefinitionConfig, AgentTelegramChannelConfig, AgentWebhookHookConfig, AgentWorkspaceInput, AgentWorkspaceRef, AgentWorkspaceRefInput, AgentZaloChannelConfig, AnyChannelDefinition, AnyResource, AsyncAgentRun, AsyncPollOptions, AsyncRequestAccepted, AsyncStatus, BroodsAccount, BroodsAccountClientOptions, BroodsClientOptions, BroodsConfigDefinition, BroodsProjectConfig, BroodsWebSocketClientOptions, ChannelDefinition, ChannelMessageReceived, ChannelRecordConfig, ChannelRecordDefinitionConfig, ChannelRecordResource, ChannelReference, ChannelType, CliManifest, CliManifestResource, CliResourceKind, CreateAgentResult, CreateClientCronInput, CreateCronInput, CreateToolInput, Cron, CronDefinitionConfig, CronDoc, CronLastStatus, CronResource, CronRun, CronStatus, CustomTool, DeleteAccountResult, DiscordChannelDefinition, DiscordChannelInput, DiscordMessageSource, DiscordSource, Doc, EnvAccessor, EnvRef, EnvRefString, GeneratedIds, GitHubChannelDefinition, GitHubChannelInput, GitHubMessageSource, GitHubSource, HarnessDefinition, HarnessType, HookContext, Id, IngressMode, IngressStatus, LogLevel, ObservabilityBackfillMessage, ObservabilityClientMessage, ObservabilityErrorMessage, ObservabilityLogEntry, ObservabilityLogMessage, ObservabilityReadyMessage, ObservabilityServerMessage, ObservabilitySpanMessage, ObservabilitySpanRow, ObservabilitySubscribeMessage, ObservabilityUnsubscribeMessage, PancakeChannelDefinition, PancakeChannelInput, PancakeMessageSource, PancakeSource, PolicyDefinitionConfig, PolicyResource, ProjectDoc, ProviderConfigInput, ProviderSettingsInput, ResourceApi, ResourceDefinition, ResourceInput, ResourceKind, RotateSecretResult, Sandbox, SandboxConfig, SandboxConfigDoc, SandboxDefinitionConfig, SandboxLifecycleResult, SandboxResource, SandboxSnapshotResult, SandboxTerminalTicket, Skill, SkillDefinitionConfig, SkillResource, SkillUploadInput, SlackChannelDefinition, SlackChannelInput, SlackMessageSource, SlackSource, StageDoc, TelegramChannelDefinition, TelegramChannelInput, TelegramMessageSource, TelegramSource, ToolApprovalSummary, ToolDefinitionConfig, ToolExecuteContext, ToolExecuteOptions, ToolResource, ToolScope, UpdateAgentInput, UpdateCronInput, UpdateToolInput, WebSocketAttachInput, WebSocketClientAttachMessage, WebSocketClientCancelMessage, WebSocketClientControlMessage, WebSocketClientExecuteMessage, WebSocketClientMessage, WebSocketConstructorLike, WebSocketHandlers, WebSocketLike, WebSocketOutputMessage, WebSocketRunInput, WebSocketServerMessage, WebSocketStreamMessage, WebSocketSubscription, Workspace, WorkspaceConfig, WorkspaceConfigDoc, WorkspaceFileEntry, WorkspaceResource, ZaloChannelDefinition, ZaloChannelInput, ZaloMessageSource, ZaloSource };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{a as M,b as h,c as O}from"./chunk-wvs39trg.js";import{A as _,B as P,C as H,D as U,E as B,F as K,G as j,H as F,I as G,J as z,K as Z,L as V,M as X,d as x,e as I,n as v,o as k,p as S,q as A,r as R,s as W,t as L,u as w,v as E,w as D,x as T,y as q,z as N}from"./chunk-jrshks26.js";import"./chunk-51a2zca3.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};
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-485rxfy0.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "broods",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "CLI + TypeScript SDK for the broods agent platform.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -50,14 +50,14 @@
50
50
  "node": ">=22"
51
51
  },
52
52
  "dependencies": {
53
- "esbuild": "^0.28.1"
53
+ "esbuild": "^0.28.2"
54
54
  },
55
55
  "peerDependencies": {
56
- "ai": "^7.0.40"
56
+ "ai": "^7.0.58"
57
57
  },
58
58
  "devDependencies": {
59
- "@ai-sdk/tui": "^1.0.41",
60
- "ai": "^7.0.40",
59
+ "@ai-sdk/tui": "^1.0.59",
60
+ "ai": "^7.0.58",
61
61
  "@chat-adapter/discord": "^4.35.0",
62
62
  "@chat-adapter/github": "^4.35.0",
63
63
  "@chat-adapter/slack": "^4.35.0",
@@ -1 +0,0 @@
1
- import{O as a}from"./chunk-7krsz9m4.js";import"./chunk-51a2zca3.js";export default a();
@@ -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*I(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 F,readFile as Z,writeFile as z}from"node:fs/promises";import{homedir as V}from"node:os";import{dirname as Y,join as X}from"node:path";var xe="broods",Ie="_generated",m=X(V(),".broods","config.json"),E="broods.app",D="dashboard",Q="gateway";async function Ee(){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 Z(m,"utf8"));if(typeof t.baseUrl!=="string"||!t.baseUrl)return null;return t}catch{return null}}async function De(e){await F(Y(m),{recursive:!0}),await z(m,`${JSON.stringify(e,null,2)}
3
- `,"utf8")}function g(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(`${D}.`))return;let t=n.hostname.slice(D.length+1);if(t!==E&&!t.endsWith(`.${E}`))return;return n.hostname=`${Q}.${t}`,g(n.origin)}catch{return}}import{existsSync as ee,readFileSync as N,statSync as ne}from"node:fs";import{join as te,resolve as oe}from"node:path";var x=new Map,re=new Set(Object.keys(process.env)),T=new Set;function k(e=process.cwd()){se(e);let n=ce();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,environment:process.env.BROODS_ENVIRONMENT}}function se(e){let n=oe(e),t=process.env.BROODS_RELOAD_ENV==="1";for(let o of[".env",".env.local"]){let r=te(n,o);if(!ee(r)){x.delete(r);continue}let s=ne(r).mtimeMs,i=x.get(r);if(i&&i.mtimeMs===s)continue;x.set(r,{mtimeMs:s});for(let[a,l]of Object.entries(ie(N(r,"utf8"))))if(t||!re.has(a)||T.has(a))process.env[a]=l,T.add(a)}}function ie(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]=ae(r.slice(s+1).trim())}return n}function ae(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 ce(){try{let e=JSON.parse(N(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 U extends Error{accepted;constructor(e){super(`Ingress ${e.eventId} was accepted asynchronously with status ${e.status??"queued"}`);this.accepted=e;this.name="IngressAcceptedError"}}class le{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=P(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 U(O(await s.json(),o));if(!s.body)throw Error("Run response has no body");for await(let i of I(s.body)){let a;try{a=JSON.parse(i)}catch{continue}if(a.type==="error")throw Error(`Agent run failed: ${ye(a.error)}`);yield a}}async runAsync(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o=P(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 ue(s,"202 JSON")}`);let i=O(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 fe(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(pe(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.environmentSlug&&e.endpointId)return`${this.baseUrl}/v1/${encodeURIComponent(e.projectSlug)}/agents/${encodeURIComponent(e.environmentSlug)}/${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 P(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 O(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=ge(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 ge(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 ue(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 pe(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 fe(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 ye(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 me=2000,W=0,h=1;class he{baseUrl;apiKey;WebSocketImpl;connectTimeoutMs;constructor(e={}){if(k(),this.baseUrl=B(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??me}subscribe(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=Se(e),s=M(this.baseUrl),i=new t(o),a=!1,l=!1,d=setTimeout(()=>{if(!a)y(s)},this.connectTimeoutMs),v=(c=1000,R="client closed")=>{if(l)return;if(l=!0,clearTimeout(d),e.signal?.removeEventListener("abort",S),i.readyState===h||i.readyState===W)i.close(c,R)},y=(c)=>{n.onError?.(c),v(1011,"websocket error")},J=()=>{n.onDone?.(),v(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(d),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=K(c.data);if(!R)return;let C=_(R,n);switch(n.onMessage?.(C),C.type){case"meta":n.onMeta?.(C);break;case"done":J();break;case"error":y(Error(H(C.error)));break}},i.onerror=()=>{y(s)},i.onclose=(c)=>{if(clearTimeout(d),e.signal?.removeEventListener("abort",S),l||c.code===1000)return;y(Error(c.reason||"WebSocket connection closed."))},{url:o,sendControl(c){if(i.readyState!==h)throw Error("WebSocket is not open");i.send(JSON.stringify({type:"control",...c}))},close:v}}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===W)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=K(a.data);if(!l)return;let d=_(l,n);if(n.onMessage?.(d),d.type==="done")n.onDone?.();if(d.type==="error")n.onError?.(Error(H(d.error)))},r.onerror=()=>n.onError?.(M(this.baseUrl)),r.onclose=(a)=>{if(!s&&a.code!==1000)n.onError?.(Error(a.reason||"WebSocket connection closed."))},{url:o,sendControl(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(a){n.push(a),s()},onDone(){t=!0,s()},onError(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=Re(e),t=e.projectSlug??e.agent?.projectSlug,o=e.environmentSlug??e.agent?.environmentSlug,r=t?`/${t}`:"",s=o?`/${o}`:"";return`${Ce(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 Se(e){let n=e.agentId??e.agent?.id??e.endpointId;if(!n)throw Error("WebSocket run requires agent, agentId, or endpointId.");return n}function Re(e){let n=e.endpointId??e.agent?.endpointId??e.agent?.id;if(!n)throw Error("WebSocket run requires agent or endpointId.");return n}function Ce(e){let n=new URL(B(e));if(n.protocol==="https:")n.protocol="wss:";if(n.protocol==="http:")n.protocol="ws:";return g(n.toString())}function B(e){let n=e.trim();if(/^wss?:\/\//.test(n))return g(n);return w(n)}function M(e){return Error(`Cannot access the WebSocket service at ${e}.`)}function _(e,n){if(e.type!=="output")return e;let t=e;return n.onOutput?.(t),t.data}function K(e){try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}function H(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 L=Symbol.for("broods.resource"),q=Symbol.for("broods.config"),G=Symbol.for("broods.channel"),j=/^[A-Z][A-Z0-9_]{0,63}$/;var Je=new Proxy((e)=>{if(!j.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(e,n,t){if(typeof n==="string"&&j.test(n))throw Error(`env.${n} is not supported; use env("${n}")`);return Reflect.get(e,n,t)}});function u(e,n,t,o){return{[L]:!0,kind:e,name:n,...t?{description:t}:{},config:o}}function f(e,n){let{workspaceScope:t,...o}=n;return{[G]:!0,kind:"channel",type:e,...t?{workspaceScope:t}:{},config:{...o,...t?{workspaceScope:t}:{}}}}function Fe(e){return f("telegram",e)}function Ze(e){return f("github",e)}function ze(e){return f("slack",e)}function Ve(e){return f("discord",e)}function Ye(e){return f("pancake",e)}function Xe(e){return f("zalo",e)}function Qe(e){return{[q]:!0,config:e}}function en(e){let{name:n,description:t,...o}=e;return u("agent",n,t,o)}function nn(e){return e}function tn(e){let{name:n,description:t,...o}=e;return u("workspace",n,t,o)}function on(e){let{name:n,description:t,...o}=e;return u("sandbox",n,t,o)}function rn(e){let{name:n,description:t,...o}=e;return u("skill",n,t,o)}function sn(e){let{name:n,...t}=e;return u("tool",n,void 0,t)}function an(e){let{name:n,description:t,...o}=e;return u("policy",n,t,o)}function cn(e){let{name:n,description:t,...o}=e;return u("channelRecord",n,t,o)}function ln(e){let{name:n,description:t,...o}=e;return u("cron",n,t,o)}function gn(e){return Boolean(e&&typeof e==="object"&&e[L])}function dn(e){return Boolean(e&&typeof e==="object"&&e[G])}function un(e){return Boolean(e&&typeof e==="object"&&e[q])}
5
- export{b as d,I as e,xe as f,Ie as g,m as h,Ee as i,De as j,g as k,Te as l,k as m,A as n,U as o,le as p,w as q,he as r,Ce as s,Je as t,Fe 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,dn as L,un as M};
@@ -1,2 +0,0 @@
1
- var c=/^[A-Z][A-Z0-9_]*$/;function u(e){if(!c.test(e)||e.length>64)throw Error("envPlaceholder name must match /^[A-Z][A-Z0-9_]*$/ and be at most 64 characters.");return`\${${e}}`}class o extends Error{status;body;constructor(e,t,n,s){super(`${e} ${t} failed with ${n}: ${s}`);this.name="BroodsAccountApiError",this.status=n,this.body=s}}function i(e){return typeof process<"u"?process?.env?.[e]:void 0}function a(e){return`?${new URLSearchParams({project:e.project,environment:e.environment}).toString()}`}class l{baseUrl;accountSecret;fetchImpl;constructor(e={}){let t=e.baseUrl??i("BROODS_BASE_URL")??"https://gateway.broods.app",n=e.accountSecret??i("BROODS_ACCOUNT_SECRET");if(!n)throw Error("BroodsAccountClient requires an accountSecret (or BROODS_ACCOUNT_SECRET).");let s=t.length;while(s>0&&t.charCodeAt(s-1)===47)s-=1;this.baseUrl=t.slice(0,s),this.accountSecret=n,this.fetchImpl=e.fetch??fetch}async getAccount(){let e=await this.request("GET","/v1/account");if(!e)throw new o("GET","/v1/account",404,"Account not found");return e.account}async updateAccount(e){return(await this.request("PATCH","/v1/account",e))?.account??null}async rotateSecret(){let e=await this.request("POST","/v1/account/rotate-secret");if(!e)throw new o("POST","/v1/account/rotate-secret",404,"Account not found");return e}async deleteAccount(){return await this.request("DELETE","/v1/account")??{deleted:!1}}webhookUrl(e,t){let n=[e,t].map(encodeURIComponent);return`${this.baseUrl}/webhooks/${n.join("/")}`}async listAgents(){return(await this.request("GET","/v1/agents"))?.agents??[]}async createAgent(e){let t=await this.request("POST","/v1/agents",e);if(!t)throw new o("POST","/v1/agents",404,"Not found");return t}async getAgent(e){return await this.request("GET",`/v1/agents/${encodeURIComponent(e)}`)}async updateAgent(e,t){return await this.request("PATCH",`/v1/agents/${encodeURIComponent(e)}`,t)}async deleteAgent(e){return(await this.request("DELETE",`/v1/agents/${encodeURIComponent(e)}`))?.deleted??!1}async listEnvVars(){return(await this.request("GET","/v1/env"))?.env??[]}async setEnvVar(e,t){await this.request("PUT",`/v1/env/${encodeURIComponent(e)}`,{value:t})}async deleteEnvVar(e){return(await this.request("DELETE",`/v1/env/${encodeURIComponent(e)}`))?.deleted??!1}async listCrons(){return(await this.request("GET","/v1/crons"))?.crons??[]}async createCron(e){let t=await this.request("POST","/v1/crons",e);if(!t)throw new o("POST","/v1/crons",404,"Not found");return t}async getCron(e){return await this.request("GET",`/v1/crons/${encodeURIComponent(e)}`)}async updateCron(e,t){return await this.request("PATCH",`/v1/crons/${encodeURIComponent(e)}`,t)}async deleteCron(e){return(await this.request("DELETE",`/v1/crons/${encodeURIComponent(e)}`))?.deleted??!1}async listCronRuns(e,t={}){let n=t.limit!==void 0?`?limit=${t.limit}`:"";return(await this.request("GET",`/v1/crons/${encodeURIComponent(e)}/runs${n}`))?.runs??[]}async listWorkspaces(){return(await this.request("GET","/v1/workspaces"))?.workspaces??[]}async createWorkspace(e){let t=await this.request("POST","/v1/workspaces",e);if(!t)throw new o("POST","/v1/workspaces",404,"Not found");return t}async getWorkspace(e){return await this.request("GET",`/v1/workspaces/${encodeURIComponent(e)}`)}async updateWorkspace(e,t){return await this.request("PATCH",`/v1/workspaces/${encodeURIComponent(e)}`,t)}async deleteWorkspace(e){return(await this.request("DELETE",`/v1/workspaces/${encodeURIComponent(e)}`))?.deleted??!1}async listWorkspaceFiles(e){return(await this.request("GET",`/v1/workspaces/${encodeURIComponent(e)}/files`))?.files??[]}async getWorkspaceFileUrl(e,t){let n=`?path=${encodeURIComponent(t)}`;return(await this.request("GET",`/v1/workspaces/${encodeURIComponent(e)}/files${n}`))?.url??null}async uploadWorkspaceFile(e,t){let n=`/v1/workspaces/${encodeURIComponent(e)}/files`,s=await this.request("POST",n,t);if(!s)throw new o("POST",n,404,"Workspace not found");return s.file}async renameWorkspaceFile(e,t,n){return(await this.request("PATCH",`/v1/workspaces/${encodeURIComponent(e)}/files`,{path:t,newPath:n}))?.renamed??!1}async deleteWorkspaceFile(e,t){return(await this.request("DELETE",`/v1/workspaces/${encodeURIComponent(e)}/files`,{path:t}))?.deleted??!1}async listSandboxes(){return(await this.request("GET","/v1/sandboxes"))?.sandboxes??[]}async createSandbox(e){let t=await this.request("POST","/v1/sandboxes",e);if(!t)throw new o("POST","/v1/sandboxes",404,"Not found");return t}async getSandbox(e){return await this.request("GET",`/v1/sandboxes/${encodeURIComponent(e)}`)}async updateSandbox(e,t){return await this.request("PATCH",`/v1/sandboxes/${encodeURIComponent(e)}`,t)}async deleteSandbox(e){return(await this.request("DELETE",`/v1/sandboxes/${encodeURIComponent(e)}`))?.deleted??!1}async suspendSandbox(e,t){return await this.sandboxAction(e,"suspend",{reservationKey:t})}async resumeSandbox(e,t){return await this.sandboxAction(e,"resume",{reservationKey:t})}async terminateSandbox(e,t){return await this.sandboxAction(e,"terminate",{reservationKey:t})}async snapshotSandbox(e,t,n){return await this.sandboxAction(e,"snapshot",{reservationKey:t,name:n})}async openSandboxTerminal(e,t){return await this.sandboxAction(e,"terminal",{reservationKey:t})}async listTools(e){let t=`/v1/tools${a(e)}`,n=await this.request("GET",t);if(!n)throw new o("GET",t,404,"Not found");return n.tools??[]}async createTool(e,t){let n=`/v1/tools${a(e)}`,s=await this.request("POST",n,t);if(!s)throw new o("POST",n,404,"Not found");return s}async getTool(e){return await this.request("GET",`/v1/tools/${encodeURIComponent(e)}`)}async updateTool(e,t){return await this.request("PATCH",`/v1/tools/${encodeURIComponent(e)}`,t)}async deleteTool(e){return(await this.request("DELETE",`/v1/tools/${encodeURIComponent(e)}`))?.deleted??!1}async listPolicies(){return(await this.request("GET","/v1/policies"))?.policies??[]}async createPolicy(e){let t=await this.request("POST","/v1/policies",e);if(!t)throw new o("POST","/v1/policies",404,"Not found");return t}async getPolicy(e){return await this.request("GET",`/v1/policies/${encodeURIComponent(e)}`)}async updatePolicy(e,t){return await this.request("PATCH",`/v1/policies/${encodeURIComponent(e)}`,t)}async deletePolicy(e){return(await this.request("DELETE",`/v1/policies/${encodeURIComponent(e)}`))?.deleted??!1}async listChannels(){return(await this.request("GET","/v1/channels"))?.channels??[]}async createChannel(e){let t=await this.request("POST","/v1/channels",e);if(!t)throw new o("POST","/v1/channels",404,"Not found");return t}async getChannel(e){return await this.request("GET",`/v1/channels/${encodeURIComponent(e)}`)}async updateChannel(e,t){return await this.request("PATCH",`/v1/channels/${encodeURIComponent(e)}`,t)}async deleteChannel(e){return(await this.request("DELETE",`/v1/channels/${encodeURIComponent(e)}`))?.deleted??!1}async listSkills(){return(await this.request("GET","/v1/skills"))?.skills??[]}async createSkill(e){let t=await this.request("POST","/v1/skills",e);if(!t)throw new o("POST","/v1/skills",404,"Not found");return t}async getSkill(e){return await this.request("GET",`/v1/skills/${encodeURIComponent(e)}`)}async uploadSkill(e,t){let n=`/v1/skills/${encodeURIComponent(e)}`,s=await this.request("PUT",n,t);if(!s)throw new o("PUT",n,404,"Skill not found");return s}async deleteSkill(e){return(await this.request("DELETE",`/v1/skills/${encodeURIComponent(e)}`))?.deleted??!1}async sandboxAction(e,t,n){let s=`/v1/sandboxes/${encodeURIComponent(e)}/${t}`,r=await this.request("POST",s,n);if(!r)throw new o("POST",s,404,"Sandbox not found");return r}async request(e,t,n){let s=await this.fetchImpl(`${this.baseUrl}${t}`,{method:e,headers:{Authorization:`Bearer ${this.accountSecret}`,...n!==void 0?{"Content-Type":"application/json"}:{}},...n!==void 0?{body:JSON.stringify(n)}:{}});if(s.status===404)return null;if(!s.ok)throw new o(e,t,s.status,await s.text());return await s.json()}}
2
- export{u as a,o as b,l as c};