broods 0.44.0 → 0.45.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
@@ -178,10 +178,11 @@ interface McpOauth {
178
178
  }
179
179
 
180
180
  /**
181
- * Agent configuration: types for the per-agent settings object, the runtime
182
- * projection of a stored config, and encryption helpers. The validation rules
183
- * are the config plane's (`@broods/convex/model/agentRules`), so a config is
184
- * judged the same on write and on every run.
181
+ * Agent configuration: types for the per-agent settings object and the
182
+ * runtime projection of a stored config. The validation rules are the config
183
+ * plane's (`@broods/convex/model/agentRules`), so a config is judged the same
184
+ * on write and on every run. Decrypting the stored blob is
185
+ * `../convex/account-keys.ts`.
185
186
  * Account types and auth live in `./accounts.ts` and `../auth.ts`.
186
187
  */
187
188
 
@@ -733,17 +734,24 @@ type UpdateCronInput = {
733
734
  input?: never;
734
735
  });
735
736
 
737
+ /**
738
+ * The sandbox provider list: the one list the schema validator, the config
739
+ * rules, core's executor registry and the SDK derive from. A leaf on purpose,
740
+ * so `schema.ts` can read it without pulling the rules' import graph.
741
+ */
742
+ declare const SANDBOX_PROVIDERS: readonly ["sandbox", "lambda", "e2b", "daytona", "vercel", "machine", "custom"];
743
+ type SandboxProvider = (typeof SANDBOX_PROVIDERS)[number];
744
+
736
745
  /**
737
746
  * Sandbox-config validation for the Convex config plane. Ports core's former
738
747
  * storage/sandbox-config.ts normalizer so the public /v1/sandboxes contract
739
748
  * is unchanged. The public projection lives in ./responses.ts.
740
749
  */
741
- declare const SANDBOX_PROVIDERS: readonly ["sandbox", "lambda", "e2b", "daytona", "vercel", "machine"];
750
+
742
751
  declare const SANDBOX_RUNTIMES: readonly ["bash", "python", "node"];
743
752
  declare const SANDBOX_PERMISSION_MODES: readonly ["edit", "ask", "bypass"];
744
753
  declare const SANDBOX_NETWORK_MODES: readonly ["allow-all", "deny-all", "restricted"];
745
754
  declare const SANDBOX_SIZE_NAMES: readonly ["tiny", "xsmall", "small", "medium", "large"];
746
- type SandboxProvider = (typeof SANDBOX_PROVIDERS)[number];
747
755
  type RuntimeName = (typeof SANDBOX_RUNTIMES)[number];
748
756
  type PermissionMode = (typeof SANDBOX_PERMISSION_MODES)[number];
749
757
  type NetworkMode = (typeof SANDBOX_NETWORK_MODES)[number];
@@ -782,6 +790,81 @@ interface SandboxConfig {
782
790
  options?: Record<string, unknown>;
783
791
  }
784
792
 
793
+ /**
794
+ * Sandbox config: account-scoped, reusable sandbox definitions referenced by
795
+ * agents via `config.sandboxes`. A sandbox is a collection of Claude-Code-style
796
+ * tools (bash/read/write/edit/glob/grep) backed by a provider. Stored encrypted
797
+ * at rest because `envVars`/`options` may hold secrets. Validation and the
798
+ * public projection live in packages/convex/model/sandboxRules.ts. The exec
799
+ * wire contract a sandbox server speaks is here too, since the SDK publishes it.
800
+ */
801
+
802
+ /**
803
+ * One exec, POSTed as JSON to `<endpoint>/exec`. The `lambda` MicroVM image
804
+ * speaks it and the `custom` provider lets an account point core at its own
805
+ * server that does. snake_case on purpose: the image shipped it first.
806
+ */
807
+ interface SandboxExecRequest {
808
+ /** Which interpreter runs `code`. Core sends `bash`. */
809
+ runtime: RuntimeName;
810
+ code: string;
811
+ /** Workspace namespace; selects the working directory. Absent for a stateless run. */
812
+ namespace?: string;
813
+ /** Root the namespace sits under; the server picks its default when absent. */
814
+ workspace_root?: string;
815
+ /** The server kills the process and answers `timed_out: true` once this passes. */
816
+ timeout_ms: number;
817
+ /** Positional arguments for `code`. */
818
+ args?: string[];
819
+ /** The process environment, set over an empty one or the server's start-up defaults (HOME, TMPDIR, PATH). */
820
+ env: Record<string, string>;
821
+ }
822
+ /** The JSON answer to one exec; HTTP 200 even when the code failed. */
823
+ interface SandboxExecResponse {
824
+ /** False when the process failed, timed out, or the request was invalid. */
825
+ ok: boolean;
826
+ runtime?: string;
827
+ /** Null when the process was killed by the timeout. */
828
+ exit_code?: number | null;
829
+ timed_out: boolean;
830
+ /** Wall-clock time of the exec. */
831
+ duration_ms: number;
832
+ stdout: string;
833
+ stderr: string;
834
+ /** True when the server already cut stdout or stderr. */
835
+ truncated?: boolean;
836
+ /** CPU time of the exec in microseconds, for usage metering. */
837
+ cpu_usec?: number;
838
+ /** The machine's vCPU-s and GB-s above its baseline since boot. MicroVM only. */
839
+ burst?: {
840
+ vcpu_seconds: number;
841
+ gb_seconds: number;
842
+ };
843
+ }
844
+
845
+ /**
846
+ * Workspace isolation levels, the one list the config plane, core, the
847
+ * dashboard and the CLI read. No imports on purpose: the CLI bundles this file
848
+ * without the Convex runtime behind workspaceRules (like modelProviders.ts).
849
+ */
850
+ declare const WORKSPACE_ISOLATION_LEVELS: readonly ["conversation", "agent"];
851
+ /**
852
+ * How a workspace splits its files. "conversation" mounts a folder per channel
853
+ * partition, "agent" gives every attached agent its own folder. Unset shares
854
+ * one root between every agent and conversation.
855
+ */
856
+ type WorkspaceIsolation = (typeof WORKSPACE_ISOLATION_LEVELS)[number];
857
+
858
+ /**
859
+ * Workspace-config validation for the Convex config plane. Ports core's
860
+ * former storage/workspace-config.ts normalizer so the public /v1/workspaces
861
+ * contract is unchanged. Workspace config holds no secrets (a roleArn is not
862
+ * a secret), so it is stored and returned in plaintext. Pure module, safe
863
+ * for the default Convex runtime. The public projection lives in
864
+ * ./responses.ts. Core runs the storage access rule too, so it reads the env
865
+ * names of both sides.
866
+ */
867
+
785
868
  declare const WORKSPACE_STORAGE_PROVIDERS: readonly ["s3"];
786
869
  type WorkspaceStorageProvider = (typeof WORKSPACE_STORAGE_PROVIDERS)[number];
787
870
  type WorkspaceStorageAuth = {
@@ -799,9 +882,13 @@ interface WorkspaceStorageConfig {
799
882
  prefix?: string;
800
883
  auth?: WorkspaceStorageAuth;
801
884
  }
885
+ /** What the API accepts: the boolean spelling of isolation is stored as its level. */
886
+ type WorkspaceConfigInput = Omit<WorkspaceConfig, "isolation"> & {
887
+ isolation?: WorkspaceIsolation | boolean;
888
+ };
802
889
  interface WorkspaceConfig {
803
890
  storage: WorkspaceStorageConfig;
804
- isolation?: boolean;
891
+ isolation?: WorkspaceIsolation;
805
892
  harness?: {
806
893
  workspace?: {
807
894
  enabled?: boolean;
@@ -823,7 +910,7 @@ declare const AGENT_POLICY_ACTIONS: readonly ["agent.invoke", "tool.call", "work
823
910
  * resource route. Roles carry the same PolicyDocument shape as agent policies;
824
911
  * each caller passes its action set to `normalizePolicyDocument`.
825
912
  */
826
- declare const API_POLICY_ACTIONS: readonly ["account:read", "account:write", "agents:read", "agents:write", "channels:read", "channels:write", "crons:read", "crons:write", "env:read", "env:write", "hooks:read", "hooks:write", "mcp:read", "mcp:write", "policies:read", "policies:write", "sandboxes:read", "sandboxes:write", "skills:read", "skills:write", "workspaces:read", "workspaces:write"];
913
+ declare const API_POLICY_ACTIONS: readonly ["account:read", "account:write", "agents:read", "agents:write", "audit:read", "audit:write", "channels:read", "channels:write", "crons:read", "crons:write", "env:read", "env:write", "hooks:read", "hooks:write", "mcp:read", "mcp:write", "policies:read", "policies:write", "sandboxes:read", "sandboxes:write", "skills:read", "skills:write", "workspaces:read", "workspaces:write"];
827
914
  type AgentPolicyAction = (typeof AGENT_POLICY_ACTIONS)[number];
828
915
  type ApiPolicyAction = (typeof API_POLICY_ACTIONS)[number];
829
916
  type PolicyAction = AgentPolicyAction | ApiPolicyAction;
@@ -1222,7 +1309,6 @@ interface PendingQuestion {
1222
1309
  label: string;
1223
1310
  description?: string;
1224
1311
  }[];
1225
- allowFreeText?: boolean;
1226
1312
  }[];
1227
1313
  }
1228
1314
  /** Answers one open prompt: option labels or free text, keyed by question id. */
@@ -1606,7 +1692,7 @@ interface BroodsClientOptions {
1606
1692
  baseUrl?: string;
1607
1693
  /** Hostname or URL of the core service. `gateway.broods.app` becomes `https://gateway.broods.app`. */
1608
1694
  host?: string;
1609
- /** API key used as the Bearer token for direct runtime calls. */
1695
+ /** Runtime key used as the Bearer token for direct runtime calls. */
1610
1696
  apiKey?: string;
1611
1697
  fetch?: typeof fetch;
1612
1698
  }
@@ -1754,7 +1840,7 @@ interface Connection {
1754
1840
  * server runtimes, as well as Node and Bun.
1755
1841
  *
1756
1842
  * Auth: every call sends `Authorization: Bearer {accountSecret}` to
1757
- * `{baseUrl}/v1/...`, or a short-lived `fp_sts_` role session token from
1843
+ * `{baseUrl}/v1/...`, or a short-lived `bsts_` role session token from
1758
1844
  * `assumeRole()`, limited to what the role's policy allows. Secrets inside
1759
1845
  * agent configs are encrypted at rest by the platform and come back redacted
1760
1846
  * (`********`) on reads.
@@ -1767,11 +1853,11 @@ type ConfigPatch<T> = T extends readonly unknown[] ? T : T extends object ? {
1767
1853
  interface BroodsAccountClientOptions {
1768
1854
  /** Base URL of the broods gateway. Falls back to `BROODS_BASE_URL`, then `https://gateway.broods.app`. */
1769
1855
  baseUrl?: string;
1770
- /** Account secret used as the Bearer token. Falls back to `BROODS_ACCOUNT_SECRET`. */
1856
+ /** Account key used as the Bearer token. Falls back to `BROODS_ACCOUNT_SECRET`. */
1771
1857
  accountSecret?: string;
1772
1858
  /**
1773
- * Short-lived `fp_sts_` role session token (from {@link BroodsAccountClient.assumeRole})
1774
- * used as the Bearer instead of the account secret. The session can only do
1859
+ * Short-lived `bsts_` role session token (from {@link BroodsAccountClient.assumeRole})
1860
+ * used as the Bearer instead of the account key. The session can only do
1775
1861
  * what its role's policy allows. Falls back to `BROODS_SESSION_TOKEN`.
1776
1862
  */
1777
1863
  sessionToken?: string;
@@ -1782,6 +1868,8 @@ interface BroodsAccount {
1782
1868
  accountId: string;
1783
1869
  username: string;
1784
1870
  status: string;
1871
+ /** Days an audit row is kept; absent means the 90 day default. */
1872
+ auditRetentionDays?: number;
1785
1873
  [key: string]: unknown;
1786
1874
  }
1787
1875
  /** Public agent record; `config` comes back with secret values redacted. */
@@ -1857,7 +1945,7 @@ interface AccountPolicy {
1857
1945
  /**
1858
1946
  * Public account-role record returned by the roles routes. The policy uses the
1859
1947
  * API action namespace (`"agents:read"`, `"crons:write"`, ...); `projectId` and
1860
- * `stageId` bound which stage runtime keys may assume the role.
1948
+ * `stageId` bound which runtime keys may assume the role.
1861
1949
  */
1862
1950
  interface AccountRole {
1863
1951
  accountId: string;
@@ -1870,9 +1958,82 @@ interface AccountRole {
1870
1958
  createdAt: string;
1871
1959
  updatedAt: string;
1872
1960
  }
1961
+ /** One link of an agent actor's delegation chain: who asked, or an agent that delegated. */
1962
+ type AuditPrincipalLink = {
1963
+ kind: "user";
1964
+ id: string;
1965
+ name?: string;
1966
+ channel?: string;
1967
+ } | {
1968
+ kind: "api";
1969
+ keyKind: "account" | "deployment" | "cron";
1970
+ } | {
1971
+ kind: "agent";
1972
+ agentId: string;
1973
+ };
1974
+ /**
1975
+ * One row of the account's hash-chained audit ledger, as `GET /v1/audit`
1976
+ * serves it. `hash` is sha256 over the canonical JSON of every field but
1977
+ * `hash` itself (an absent optional field is left out, not null), with
1978
+ * `prevHash` linking it to the row before.
1979
+ */
1980
+ interface AuditEvent {
1981
+ accountId: string;
1982
+ seq: number;
1983
+ prevHash: string;
1984
+ hash: string;
1985
+ /** Unix ms. */
1986
+ at: number;
1987
+ actor: {
1988
+ kind: string;
1989
+ id?: string;
1990
+ email?: string;
1991
+ name?: string;
1992
+ agentId?: string;
1993
+ /** On an agent actor: who asked, then each agent that delegated, oldest first. */
1994
+ chain?: AuditPrincipalLink[];
1995
+ };
1996
+ action: string;
1997
+ resource: {
1998
+ kind: string;
1999
+ id?: string;
2000
+ name?: string;
2001
+ };
2002
+ summary: string;
2003
+ detailsJson?: string;
2004
+ projectId?: string;
2005
+ stageId?: string;
2006
+ traceId?: string;
2007
+ }
2008
+ /** A page of ledger rows plus the chain head to compare the last row against. */
2009
+ interface AuditPage {
2010
+ events: AuditEvent[];
2011
+ /** Pass as `since` to read the rows after this page. */
2012
+ nextSince: number;
2013
+ head: {
2014
+ seq: number;
2015
+ hash: string;
2016
+ } | null;
2017
+ }
2018
+ /** Result of `GET /v1/audit/verify`: the chain recomputed over the checked range. */
2019
+ interface AuditVerification {
2020
+ ok: boolean;
2021
+ brokenAtSeq?: number;
2022
+ checkedFrom?: number;
2023
+ checkedTo?: number;
2024
+ }
2025
+ /** The account's audit export target. The signing secret never comes back. */
2026
+ interface AuditSink {
2027
+ kind: "webhook";
2028
+ url: string;
2029
+ /** Highest seq the receiver acknowledged. */
2030
+ exportedSeq: number;
2031
+ lastError?: string;
2032
+ updatedAt: string;
2033
+ }
1873
2034
  /** Short-lived role session minted by `POST /v1/account/assume-role`. */
1874
2035
  interface AssumeRoleResult {
1875
- /** `fp_sts_` bearer token; pass it as `sessionToken` to a new client. */
2036
+ /** `bsts_` bearer token; pass it as `sessionToken` to a new client. */
1876
2037
  token: string;
1877
2038
  /** ISO timestamp when the session stops working. */
1878
2039
  expiresAt: string;
@@ -2019,7 +2180,7 @@ interface SkillUploadInput {
2019
2180
  }>;
2020
2181
  url?: string;
2021
2182
  }
2022
- /** Result of `POST /v1/account/rotate-secret`. The returned `secret` is shown once; the old secret stops working immediately. */
2183
+ /** Result of `POST /v1/account/rotate-secret`. The returned `secret` is the new account key, shown once; the old key stops working immediately. */
2023
2184
  interface RotateSecretResult {
2024
2185
  account: BroodsAccount;
2025
2186
  secret: string;
@@ -2055,7 +2216,7 @@ declare class BroodsAccountApiError extends Error {
2055
2216
  declare function envPlaceholder(name: string): string;
2056
2217
  /**
2057
2218
  * The credential the environment supplies, with a role session winning over
2058
- * the account secret. The constructor throws through this same resolution, so
2219
+ * the account key. The constructor throws through this same resolution, so
2059
2220
  * callers that can run without an account credential (`broods mcp` with only a
2060
2221
  * stored login) probe here instead of catching the constructor.
2061
2222
  */
@@ -2077,17 +2238,19 @@ declare class BroodsAccountClient {
2077
2238
  updateAccount(patch: {
2078
2239
  username?: string;
2079
2240
  description?: string | null;
2241
+ /** 1 to 3650 days, or null to return to the 90 day default. */
2242
+ auditRetentionDays?: number | null;
2080
2243
  }): Promise<BroodsAccount | null>;
2081
2244
  /**
2082
- * Exchange a role for a short-lived `fp_sts_` session token. Callable with
2083
- * the account secret, a CLI login token, or a stage runtime key (the latter
2245
+ * Exchange a role for a short-lived `bsts_` session token. Callable with
2246
+ * the account key, a CLI login token, or a runtime key (the latter
2084
2247
  * only into roles scoped to the key's own project/stage). Construct a new
2085
2248
  * client with `{ sessionToken: result.token }` to act as the role.
2086
2249
  */
2087
2250
  assumeRole(roleId: string, options?: {
2088
2251
  ttlSeconds?: number;
2089
2252
  }): Promise<AssumeRoleResult>;
2090
- /** Rotate the account secret. The returned `secret` is shown once and the current secret stops working immediately, so persist it before the process exits. */
2253
+ /** Rotate the account key. The returned `secret` is the new key, shown once, and the current key stops working immediately, so persist it before the process exits. */
2091
2254
  rotateSecret(): Promise<RotateSecretResult>;
2092
2255
  /** Delete this account and cascade-clean every account-scoped resource. `cleanup` reports per-resource deletion counts. */
2093
2256
  deleteAccount(): Promise<DeleteAccountResult>;
@@ -2138,13 +2301,13 @@ declare class BroodsAccountClient {
2138
2301
  createWorkspace(input: {
2139
2302
  name: string;
2140
2303
  description?: string;
2141
- config?: WorkspaceConfig;
2304
+ config?: WorkspaceConfigInput;
2142
2305
  }): Promise<AccountWorkspace>;
2143
2306
  getWorkspace(workspaceId: string): Promise<AccountWorkspace | null>;
2144
2307
  updateWorkspace(workspaceId: string, patch: {
2145
2308
  name?: string;
2146
2309
  description?: string | null;
2147
- config?: ConfigPatch<WorkspaceConfig>;
2310
+ config?: ConfigPatch<WorkspaceConfigInput>;
2148
2311
  }): Promise<AccountWorkspace | null>;
2149
2312
  deleteWorkspace(workspaceId: string): Promise<boolean>;
2150
2313
  /** Flat listing of every file in the workspace's S3-backed filesystem. Returns [] when the workspace is gone. */
@@ -2231,6 +2394,32 @@ declare class BroodsAccountClient {
2231
2394
  status?: "active" | "disabled";
2232
2395
  }): Promise<AccountRole | null>;
2233
2396
  deleteRole(roleId: string): Promise<boolean>;
2397
+ /** The audit ledger: rows since a seq, chain verification, and the webhook sink. */
2398
+ readonly audit: {
2399
+ /** Rows with `seq > since`, oldest first, at most `limit` (default 100, max 500). */
2400
+ list: (options?: {
2401
+ since?: number;
2402
+ limit?: number;
2403
+ }) => Promise<AuditPage>;
2404
+ /**
2405
+ * Recompute the chain over `[fromSeq, toSeq]`, from the oldest kept row by
2406
+ * default, at most 1000 rows per call. `ok` covers only `checkedFrom` to
2407
+ * `checkedTo`; on a longer ledger call again with `fromSeq: checkedTo + 1`.
2408
+ */
2409
+ verify: (options?: {
2410
+ fromSeq?: number;
2411
+ toSeq?: number;
2412
+ }) => Promise<AuditVerification>;
2413
+ /** The account's sink, or null when none is set. */
2414
+ getSink: () => Promise<AuditSink | null>;
2415
+ /** Set the one webhook sink. `url` must be public https; `secret` signs each batch. */
2416
+ setSink: (input: {
2417
+ url: string;
2418
+ secret: string;
2419
+ }) => Promise<AuditSink>;
2420
+ /** Remove the sink; exports stop and rows age out on retention alone. Returns whether one existed. */
2421
+ deleteSink: () => Promise<boolean>;
2422
+ };
2234
2423
  listChannels(): Promise<AccountChannel[]>;
2235
2424
  /** Bind one real chat channel to an agent. One active record per place. */
2236
2425
  createChannel(input: {
@@ -2314,7 +2503,7 @@ interface BroodsWebSocketClientOptions {
2314
2503
  baseUrl?: string;
2315
2504
  /** Hostname or URL of the core service. `gateway.broods.app` becomes `https://gateway.broods.app`. */
2316
2505
  host?: string;
2317
- /** API key used as the WebSocket token. Defaults to BROODS_API_KEY from the environment or local .env files. */
2506
+ /** Runtime key used as the WebSocket token. Defaults to BROODS_API_KEY from the environment or local .env files. */
2318
2507
  apiKey?: string;
2319
2508
  WebSocket?: WebSocketConstructorLike;
2320
2509
  connectTimeoutMs?: number;
@@ -2414,9 +2603,15 @@ type ResourceInput<Name extends string, Config> = {
2414
2603
  * `persistent` sandbox reconnects to when no workspace is mounted; unset, each
2415
2604
  * agent gets its own, and pinning one string on two sandboxes shares a machine.
2416
2605
  * Keys are scoped to the account, so they cannot reach another account's machine.
2606
+ * A `custom` sandbox names its server with `endpoint` (https, required), an
2607
+ * optional bearer `token` and extra static `headers`; a credential header's
2608
+ * value is an `env("NAME")` ref.
2417
2609
  */
2418
2610
  type SandboxDefinitionOptions = Record<string, unknown> & {
2419
2611
  reservationKey?: string;
2612
+ endpoint?: string;
2613
+ token?: string | EnvRef;
2614
+ headers?: Record<string, string | EnvRef>;
2420
2615
  };
2421
2616
  /**
2422
2617
  * Code-first sandbox config input. Mirrors core's `SandboxConfig` but lets
@@ -2917,7 +3112,7 @@ type AgentDefinitionConfig = EnvRefString<Pick<AgentConfig, "agent" | "model" |
2917
3112
  policies?: readonly (PolicyResource | string)[];
2918
3113
  /**
2919
3114
  * Opt the agent into the public runtime endpoint (SSE/WebSocket via the
2920
- * stage runtime key). Off by default: when unset the public endpoint
3115
+ * runtime key). Off by default: when unset the public endpoint
2921
3116
  * refuses requests for this agent. Reach a private agent through an
2922
3117
  * internal endpoint or a channel webhook. See issue #65.
2923
3118
  */
@@ -2934,12 +3129,13 @@ type CronDefinitionConfig = Omit<CreateCronInput, "agentId" | "name"> & {
2934
3129
  type AgentResource<Name extends string = string> = ResourceDefinition<"agent", Name, AgentDefinitionConfig>;
2935
3130
  /**
2936
3131
  * Code-first workspace config. Says `partitioned` where storage says
2937
- * `isolation`: the flag permits a split, it does not perform one. A channel's
2938
- * `partition` decides which folder a run mounts.
3132
+ * `isolation`. `true` or "conversation" permits a per-conversation split that
3133
+ * a channel's `partition` performs; "agent" splits the workspace per attached
3134
+ * agent on its own, with no partition needed.
2939
3135
  */
2940
3136
  type WorkspaceDefinitionConfig = Omit<WorkspaceConfig, "isolation"> & {
2941
- /** Allow this workspace to be split into per-conversation folders. */
2942
- partitioned?: boolean;
3137
+ /** How to split this workspace: per conversation (`true`) or per agent. */
3138
+ partitioned?: boolean | WorkspaceIsolation;
2943
3139
  };
2944
3140
  type WorkspaceResource<Name extends string = string> = ResourceDefinition<"workspace", Name, WorkspaceDefinitionConfig>;
2945
3141
  type SandboxResource<Name extends string = string> = ResourceDefinition<"sandbox", Name, SandboxDefinitionConfig>;
@@ -3015,4 +3211,4 @@ declare function isConnectionDefinition(value: unknown): value is AnyConnectionD
3015
3211
  declare function isResource(value: unknown): value is AnyResource;
3016
3212
 
3017
3213
  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, defineGoogleChatChannel, defineGoogleChatConnection, defineHarness, defineInstagramChannel, defineInstagramConnection, defineLinearChannel, defineLinearConnection, defineMatrixChannel, defineMatrixConnection, defineMcp, defineMessengerChannel, defineMessengerConnection, definePancakeChannel, definePancakeConnection, definePolicy, defineSandbox, defineSkill, defineSlackChannel, defineSlackConnection, defineTeamsChannel, defineTeamsConnection, defineTelegramChannel, defineTelegramConnection, defineTwilioChannel, defineTwilioConnection, defineWhatsAppChannel, defineWhatsAppConnection, defineWorkspace, defineZaloChannel, defineZaloConnection, env, envPlaceholder, isBroodsConfig, isConnectionDefinition, isLogLevel, isObservabilityClientMessage, isResource, isRootSpanKind, isSandboxLogId, isTraceId, normalizeHttpServiceUrl, readSseStream, resolveEnvCredential, resolveRunEvents, toWebSocketBaseUrl, webSocketSubprotocols };
3018
- export type { Account, AccountAgent, AccountChannel, AccountEnvVar, AccountMcp, AccountPolicy, AccountRole, AccountSandbox, AccountWorkspace, Agent, AgentChannelsConfig, AgentCodeHookConfig, AgentConfig, AgentConfigDoc, AgentContinueInput, AgentDefinitionConfig, AgentDiscordChannelConfig, AgentGitHubChannelConfig, AgentGoogleChatChannelConfig, AgentHandle, AgentHookEventName, AgentHooks, AgentHooksConfig, AgentInstagramChannelConfig, AgentLinearChannelConfig, AgentMatrixChannelConfig, AgentMessengerChannelConfig, AgentPancakeChannelConfig, AgentProviderSettings, AgentReference, AgentResource, AgentRunAnswerInput, AgentRunEventInput, AgentRunInput, AgentRunModelOverrides, AgentRunOverrides, AgentRunResult, AgentSkillsDefinitionConfig, AgentSlackChannelConfig, AgentStreamPart, AgentSubagentDefinitionConfig, AgentTeamsChannelConfig, AgentTelegramChannelConfig, AgentTwilioChannelConfig, AgentWebhookHookConfig, AgentWhatsAppChannelConfig, 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, ConfigPatch, Connection, ConnectionCode, ConnectionDefinition, ConnectionStart, ConnectionStartResult, ConnectionType, CreateAgentResult, 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, GoogleChatChannelInput, GoogleChatConnectionDefinition, GoogleChatConnectionInput, GoogleChatMessageSource, GoogleChatSource, HarnessDefinition, HarnessType, HookAgentConfig, HookContext, Id, IngressMode, IngressStatus, InstagramChannelInput, InstagramConnectionDefinition, InstagramConnectionInput, InstagramMessageSource, InstagramSource, LinearChannelInput, LinearConnectionDefinition, LinearConnectionInput, LinearMessageSource, LinearSource, LogLevel, MatrixChannelInput, MatrixConnectionDefinition, MatrixConnectionInput, MatrixMessageSource, MatrixSource, McpDefinitionConfig, McpHandler, McpOauthInput, McpResource, MessengerChannelInput, MessengerConnectionDefinition, MessengerConnectionInput, MessengerMessageSource, MessengerSource, 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, TaskWaitingOn, TeamsChannelInput, TeamsConnectionDefinition, TeamsConnectionInput, TeamsMessageSource, TeamsSource, TelegramChannelInput, TelegramConnectionDefinition, TelegramConnectionInput, TelegramMessageSource, TelegramSource, ToolApprovalSummary, TwilioChannelInput, TwilioConnectionDefinition, TwilioConnectionInput, TwilioMessageSource, TwilioSource, UpdateAgentInput, UpdateCronInput, UpdateMcpInput, WebSocketAttachInput, WebSocketClientAttachMessage, WebSocketClientCancelMessage, WebSocketClientControlMessage, WebSocketClientExecuteMessage, WebSocketClientMessage, WebSocketConstructorLike, WebSocketHandlers, WebSocketLike, WebSocketOutputMessage, WebSocketRunInput, WebSocketServerMessage, WebSocketStreamMessage, WebSocketSubscription, WhatsAppChannelInput, WhatsAppConnectionDefinition, WhatsAppConnectionInput, WhatsAppMessageSource, WhatsAppSource, Workspace, WorkspaceConfig, WorkspaceConfigDoc, WorkspaceDefinitionConfig, WorkspaceFileEntry, WorkspaceResource, ZaloChannelInput, ZaloConnectionDefinition, ZaloConnectionInput, ZaloMessageSource, ZaloSource };
3214
+ export type { Account, AccountAgent, AccountChannel, AccountEnvVar, AccountMcp, AccountPolicy, AccountRole, AccountSandbox, AccountWorkspace, Agent, AgentChannelsConfig, AgentCodeHookConfig, AgentConfig, AgentConfigDoc, AgentContinueInput, AgentDefinitionConfig, AgentDiscordChannelConfig, AgentGitHubChannelConfig, AgentGoogleChatChannelConfig, AgentHandle, AgentHookEventName, AgentHooks, AgentHooksConfig, AgentInstagramChannelConfig, AgentLinearChannelConfig, AgentMatrixChannelConfig, AgentMessengerChannelConfig, AgentPancakeChannelConfig, AgentProviderSettings, AgentReference, AgentResource, AgentRunAnswerInput, AgentRunEventInput, AgentRunInput, AgentRunModelOverrides, AgentRunOverrides, AgentRunResult, AgentSkillsDefinitionConfig, AgentSlackChannelConfig, AgentStreamPart, AgentSubagentDefinitionConfig, AgentTeamsChannelConfig, AgentTelegramChannelConfig, AgentTwilioChannelConfig, AgentWebhookHookConfig, AgentWhatsAppChannelConfig, AgentWorkspaceInput, AgentWorkspaceRef, AgentWorkspaceRefInput, AgentZaloChannelConfig, AnyConnectionDefinition, AnyResource, AssumeRoleResult, AsyncAgentRun, AsyncPollOptions, AsyncRequestAccepted, AsyncStatus, AuditEvent, AuditPage, AuditPrincipalLink, AuditSink, AuditVerification, BroodsAccount, BroodsAccountClientOptions, BroodsClientOptions, BroodsConfigDefinition, BroodsProjectConfig, BroodsWebSocketClientOptions, ChannelAgentInput, ChannelDefinitionConfig, ChannelMessageReceived, ChannelPartition, ChannelRecordConfig, ChannelReference, ChannelReplyIn, ChannelResource, ChannelType, CliManifest, CliManifestResource, ConfigPatch, Connection, ConnectionCode, ConnectionDefinition, ConnectionStart, ConnectionStartResult, ConnectionType, CreateAgentResult, 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, GoogleChatChannelInput, GoogleChatConnectionDefinition, GoogleChatConnectionInput, GoogleChatMessageSource, GoogleChatSource, HarnessDefinition, HarnessType, HookAgentConfig, HookContext, Id, IngressMode, IngressStatus, InstagramChannelInput, InstagramConnectionDefinition, InstagramConnectionInput, InstagramMessageSource, InstagramSource, LinearChannelInput, LinearConnectionDefinition, LinearConnectionInput, LinearMessageSource, LinearSource, LogLevel, MatrixChannelInput, MatrixConnectionDefinition, MatrixConnectionInput, MatrixMessageSource, MatrixSource, McpDefinitionConfig, McpHandler, McpOauthInput, McpResource, MessengerChannelInput, MessengerConnectionDefinition, MessengerConnectionInput, MessengerMessageSource, MessengerSource, 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, SandboxExecRequest, SandboxExecResponse, SandboxLifecycleResult, SandboxProvider, SandboxResource, SandboxSnapshotResult, SandboxTerminalTicket, Skill, SkillDefinitionConfig, SkillResource, SkillUploadInput, SlackChannelInput, SlackConnectionDefinition, SlackConnectionInput, SlackMessageSource, SlackSource, StageDoc, StageScope, TaskWaitingOn, TeamsChannelInput, TeamsConnectionDefinition, TeamsConnectionInput, TeamsMessageSource, TeamsSource, TelegramChannelInput, TelegramConnectionDefinition, TelegramConnectionInput, TelegramMessageSource, TelegramSource, ToolApprovalSummary, TwilioChannelInput, TwilioConnectionDefinition, TwilioConnectionInput, TwilioMessageSource, TwilioSource, UpdateAgentInput, UpdateCronInput, UpdateMcpInput, WebSocketAttachInput, WebSocketClientAttachMessage, WebSocketClientCancelMessage, WebSocketClientControlMessage, WebSocketClientExecuteMessage, WebSocketClientMessage, WebSocketConstructorLike, WebSocketHandlers, WebSocketLike, WebSocketOutputMessage, WebSocketRunInput, WebSocketServerMessage, WebSocketStreamMessage, WebSocketSubscription, WhatsAppChannelInput, WhatsAppConnectionDefinition, WhatsAppConnectionInput, WhatsAppMessageSource, WhatsAppSource, Workspace, WorkspaceConfig, WorkspaceConfigDoc, WorkspaceConfigInput, WorkspaceDefinitionConfig, WorkspaceFileEntry, WorkspaceIsolation, WorkspaceResource, ZaloChannelInput, ZaloConnectionDefinition, ZaloConnectionInput, ZaloMessageSource, ZaloSource };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{V,ge,Me,Pe,Ne,je,G,Ie,E,ye,F,J,xe,Y,z,qe,De,Le,Ue,Fe,Be,Ze,He,Ve,Ge,We,Ke,Je,Ye,Xe,Qe,et,tt,nt,rt,ot,st,it,at,ct,lt,ut,dt,pt,mt,ht,ft,gt,yt,St,bt,vt,_t,ie,w,g}from"./chunk-t0fvmbkd.js";import{m,Ae,Z,R}from"./chunk-a3f2xzbr.js";export{m as BroodsAccountApiError,R as BroodsAccountClient,F as BroodsClient,xe as BroodsWebSocketClient,E as DEFAULT_CORE_BASE_URL,ye as IngressAcceptedError,Me as MAX_OBSERVABILITY_BACKFILL,xe as WebSocketClient,xe as WebsocketClient,De as defineAgent,Le as defineBroods,Ue as defineCron,ct as defineDiscordChannel,We as defineDiscordConnection,lt as defineGitHubChannel,Ke as defineGitHubConnection,ut as defineGoogleChatChannel,Je as defineGoogleChatConnection,Fe as defineHarness,dt as defineInstagramChannel,Ye as defineInstagramConnection,pt as defineLinearChannel,Xe as defineLinearConnection,mt as defineMatrixChannel,Qe as defineMatrixConnection,Be as defineMcp,ht as defineMessengerChannel,et as defineMessengerConnection,ft as definePancakeChannel,tt as definePancakeConnection,Ze as definePolicy,He as defineSandbox,Ve as defineSkill,gt as defineSlackChannel,nt as defineSlackConnection,yt as defineTeamsChannel,rt as defineTeamsConnection,St as defineTelegramChannel,ot as defineTelegramConnection,bt as defineTwilioChannel,st as defineTwilioConnection,vt as defineWhatsAppChannel,it as defineWhatsAppConnection,Ge as defineWorkspace,_t as defineZaloChannel,at as defineZaloConnection,qe as env,Ae as envPlaceholder,ie as isBroodsConfig,w as isConnectionDefinition,Pe as isLogLevel,Ne as isObservabilityClientMessage,g as isResource,je as isRootSpanKind,G as isSandboxLogId,Ie as isTraceId,J as normalizeHttpServiceUrl,ge as readSseStream,Z as resolveEnvCredential,V as resolveRunEvents,Y as toWebSocketBaseUrl,z as webSocketSubprotocols};
1
+ import{V,ge,Me,Pe,Ne,je,G,Ie,E,ye,F,J,xe,Y,z,qe,De,Le,Ue,Fe,Be,Ze,He,Ve,Ge,We,Ke,Je,Ye,Xe,Qe,et,tt,nt,rt,ot,st,it,at,ct,lt,ut,dt,pt,mt,ht,ft,gt,yt,St,bt,vt,_t,ie,w,g}from"./chunk-hdcy74kj.js";import{m,Ae,Z,R}from"./chunk-bb3jfhv3.js";export{m as BroodsAccountApiError,R as BroodsAccountClient,F as BroodsClient,xe as BroodsWebSocketClient,E as DEFAULT_CORE_BASE_URL,ye as IngressAcceptedError,Me as MAX_OBSERVABILITY_BACKFILL,xe as WebSocketClient,xe as WebsocketClient,De as defineAgent,Le as defineBroods,Ue as defineCron,ct as defineDiscordChannel,We as defineDiscordConnection,lt as defineGitHubChannel,Ke as defineGitHubConnection,ut as defineGoogleChatChannel,Je as defineGoogleChatConnection,Fe as defineHarness,dt as defineInstagramChannel,Ye as defineInstagramConnection,pt as defineLinearChannel,Xe as defineLinearConnection,mt as defineMatrixChannel,Qe as defineMatrixConnection,Be as defineMcp,ht as defineMessengerChannel,et as defineMessengerConnection,ft as definePancakeChannel,tt as definePancakeConnection,Ze as definePolicy,He as defineSandbox,Ve as defineSkill,gt as defineSlackChannel,nt as defineSlackConnection,yt as defineTeamsChannel,rt as defineTeamsConnection,St as defineTelegramChannel,ot as defineTelegramConnection,bt as defineTwilioChannel,st as defineTwilioConnection,vt as defineWhatsAppChannel,it as defineWhatsAppConnection,Ge as defineWorkspace,_t as defineZaloChannel,at as defineZaloConnection,qe as env,Ae as envPlaceholder,ie as isBroodsConfig,w as isConnectionDefinition,Pe as isLogLevel,Ne as isObservabilityClientMessage,g as isResource,je as isRootSpanKind,G as isSandboxLogId,Ie as isTraceId,J as normalizeHttpServiceUrl,ge as readSseStream,Z as resolveEnvCredential,V as resolveRunEvents,Y as toWebSocketBaseUrl,z as webSocketSubprotocols};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "broods",
3
- "version": "0.44.0",
3
+ "version": "0.45.0",
4
4
  "description": "CLI + TypeScript SDK for the broods agent platform.",
5
5
  "keywords": [
6
6
  "agents",
@@ -1 +0,0 @@
1
- import{j}from"./chunk-dcjq5a2g.js";import{Z,R}from"./chunk-a3f2xzbr.js";import{e,o,a,l,s}from"./chunk-naxtmb6t.js";var E={project:e().optional(),stage:e().optional()},M={sandboxId:e().min(1),reservationKey:e().min(1)},v=a().describe("Must be true, after the owner has agreed to this delete."),b="'********' keeps a stored secret and null deletes a field: never send a placeholder you did not read from a get.",A=[{singular:"agent",plural:"agents",key:"agentId",createHint:"Needs name and config; a 409 returns the existing agentId.",deleteHint:"Deleting an agent also drops its runtime rows.",updateHint:b,list:(t)=>t.listAgents(),get:(t,r)=>t.getAgent(r),create:(t,r)=>t.createAgent(r),update:(t,r,n)=>t.updateAgent(r,n),remove:(t,r)=>t.deleteAgent(r)},{singular:"cron",plural:"crons",key:"cronId",createHint:"Needs name, agentId, scheduleExpression (rate/cron/at) and input or events.",list:(t)=>t.listCrons(),get:(t,r)=>t.getCron(r),create:(t,r)=>t.createCron(r),update:(t,r,n)=>t.updateCron(r,n),remove:(t,r)=>t.deleteCron(r)},{singular:"sandbox",plural:"sandboxes",key:"sandboxId",updateHint:b,list:(t)=>t.listSandboxes(),get:(t,r)=>t.getSandbox(r),create:(t,r)=>t.createSandbox(r),update:(t,r,n)=>t.updateSandbox(r,n),remove:(t,r)=>t.deleteSandbox(r)},{singular:"workspace",plural:"workspaces",key:"workspaceId",list:(t)=>t.listWorkspaces(),get:(t,r)=>t.getWorkspace(r),create:(t,r)=>t.createWorkspace(r),update:(t,r,n)=>t.updateWorkspace(r,n),remove:(t,r)=>t.deleteWorkspace(r)},{singular:"policy",plural:"policies",key:"policyId",createHint:"Agent-runtime policy document (tool.call, skill.load), not API credential scoping.",list:(t)=>t.listPolicies(),get:(t,r)=>t.getPolicy(r),create:(t,r)=>t.createPolicy(r),update:(t,r,n)=>t.updatePolicy(r,n),remove:(t,r)=>t.deletePolicy(r)},{singular:"role",plural:"roles",key:"roleId",createHint:"Needs name and a version-1 policy over the API namespace, e.g. agents:read. Account secret only.",list:(t)=>t.listRoles(),get:(t,r)=>t.getRole(r),create:(t,r)=>t.createRole(r),update:(t,r,n)=>t.updateRole(r,n),remove:(t,r)=>t.deleteRole(r)},{singular:"channel",plural:"channels",key:"channelId",list:(t)=>t.listChannels(),get:(t,r)=>t.getChannel(r),create:(t,r)=>t.createChannel(r),update:(t,r,n)=>t.updateChannel(r,n),remove:(t,r)=>t.deleteChannel(r)},{singular:"skill",plural:"skills",key:"skillName",createHint:'source is "files" (base64), "json" or "github". The stored name comes from the SKILL.md frontmatter.',list:(t)=>t.listSkills(),get:(t,r)=>t.getSkill(r),create:(t,r)=>t.createSkill(r),remove:(t,r)=>t.deleteSkill(r)},{singular:"mcp",plural:"mcp",key:"serverId",scoped:!0,list:(t,r)=>t.listMcp(r),get:(t,r)=>t.getMcp(r),create:(t,r,n)=>t.createMcp(n,r),update:(t,r,n)=>t.updateMcp(r,n),remove:(t,r)=>t.deleteMcp(r)}];function Pt(t={}){let r=Z()?new R({}):null;if(!r&&!t.cli)throw Error("broods mcp needs a credential: set BROODS_SESSION_TOKEN or BROODS_ACCOUNT_SECRET, or run `broods login`.");let n=new j({name:"broods",version:"1"},{capabilities:{tools:{}}});if(r){for(let i of A)x(n,r,i,t.scope??{});N(n,r)}if(t.cli)O(n,t.cli);if(t.allowDestructive)q(n,r,t.cli??null);return n}function w(t,r){if(!t)throw Error(`Refusing without confirm:true. ${r}`)}async function d(t){try{return P(await t())}catch(r){return k(r)}}function k(t){return{content:[{type:"text",text:t instanceof Error?t.message:String(t)}],isError:!0}}function P(t){return{content:[{type:"text",text:JSON.stringify(t??null,null,2)}]}}function T(t,r,n,i){if(!t.scoped)return;let c=n??r.project,p=i??r.stage;if(!c||!p)throw Error(`${t.plural} live in one stage, so this call needs both 'project' and 'stage'`);return{project:c,stage:p}}function O(t,r){t.registerTool("list-orgs",{description:"Every organization this login can reach, with the current one marked.",inputSchema:{}},async()=>await d(async()=>{let n=await r.getOnboarding();return{currentOrgId:n.currentOrgId,orgs:n.orgs}})),t.registerTool("create-org",{description:"Create an organization and switch this login to it. Later calls act in the new org.",inputSchema:{name:e().min(1)}},async({name:n})=>await d(async()=>await r.createOnboardingOrg(n))),t.registerTool("select-org",{description:"Switch this login to another organization, by an orgId from list-orgs.",inputSchema:{orgId:e().min(1)}},async({orgId:n})=>await d(async()=>await r.selectOnboardingOrg(n))),t.registerTool("list-projects",{description:"Every project in the current org, empty ones last. Project names are not unique, so take the id from here.",inputSchema:{}},async()=>await d(async()=>await r.listProjects())),t.registerTool("list-stages",{description:"Every stage of one project, by project name.",inputSchema:{project:e().min(1)}},async({project:n})=>await d(async()=>await r.listStages(n))),t.registerTool("create-stage",{description:"Create a stage in a project, optionally cloning another stage's architecture and env vars. A project name that does not exist yet is created with it, which is the only way to make a project without deploying a manifest.",inputSchema:{project:e().min(1),name:e().min(1),from:e().optional().describe("Stage to clone architecture and env vars from.")}},async({project:n,name:i,from:c})=>await d(async()=>await r.createStage(n,i,c)))}function q(t,r,n){if(r)t.registerTool("rotate-secret",{description:"Rotate the account secret. The current secret stops working immediately and the new one is shown once, so this breaks every deployment and CI job still holding the old one. Requires confirm:true.",inputSchema:{confirm:v}},async({confirm:i})=>await d(async()=>(w(i,"Everything holding the current secret breaks the moment this runs."),await r.rotateSecret())));if(n)t.registerTool("delete-project",{description:"Delete a project and everything under it: stages, agents, canvas, env vars, crons and workspace files. Takes a projectId from list-projects and requires confirm:true.",inputSchema:{projectId:e().min(1),confirm:v}},async({projectId:i,confirm:c})=>await d(async()=>(w(c,`Project '${i}' and everything under it goes away: name it, get the owner's agreement, then retry.`),await n.deleteProject(i))))}function N(t,r){t.registerTool("list-cron-runs",{description:"Run history for one cron, newest first. Check this before telling anyone a cron fired.",inputSchema:{cronId:e().min(1),limit:o().int().positive().max(100).optional()}},async({cronId:i,limit:c})=>await d(async()=>await r.listCronRuns(i,c===void 0?{}:{limit:c})));let n=[["suspend-sandbox","Suspend a persistent sandbox reservation.",(i,c)=>r.suspendSandbox(i,c)],["resume-sandbox","Resume a suspended sandbox reservation.",(i,c)=>r.resumeSandbox(i,c)],["terminate-sandbox","Terminate a sandbox reservation and drop its live-instance row. Terminate only a sandbox you created, and never one holding state you did not put there.",(i,c)=>r.terminateSandbox(i,c)],["open-sandbox-terminal","Mint a short-lived sealed ticket for an interactive PTY session on a persistent sandbox.",(i,c)=>r.openSandboxTerminal(i,c)]];for(let[i,c,p]of n)t.registerTool(i,{description:c,inputSchema:M},async({sandboxId:f,reservationKey:g})=>await d(async()=>await p(f,g)));t.registerTool("snapshot-sandbox",{description:"Snapshot a sandbox reservation into a reusable image (self-hosted provider).",inputSchema:{sandboxId:e().min(1),reservationKey:e().min(1),name:e().min(1)}},async({sandboxId:i,reservationKey:c,name:p})=>await d(async()=>await r.snapshotSandbox(i,c,p))),t.registerTool("upload-skill",{description:"Replace one skill's bundle wholesale (PUT, not a merge) by skillName. 'body' is the same source shape create-skill takes.",inputSchema:{id:e().min(1).describe("The skillName."),body:s(e(),l())}},async({id:i,body:c})=>await d(async()=>await r.uploadSkill(i,c))),t.registerTool("list-env-vars",{description:"List environment variable names. Values are write-only: the plane never returns them, so there is no read.",inputSchema:{}},async()=>await d(async()=>await r.listEnvVars())),t.registerTool("set-env-var",{description:"Create or replace one write-only environment variable. Reference it from a config as ${NAME} rather than inlining the value.",inputSchema:{name:e().min(1),value:e()}},async({name:i,value:c})=>await d(async()=>(await r.setEnvVar(i,c),{name:i,stored:!0}))),t.registerTool("delete-env-var",{description:"Delete one environment variable.",inputSchema:{name:e().min(1),confirm:v}},async({name:i,confirm:c})=>await d(async()=>(w(c,`Anything referencing \${${i}} breaks the moment this env var goes.`),{deleted:await r.deleteEnvVar(i),name:i}))),t.registerTool("assume-role",{description:"Exchange a role for a short-lived session token (default 1h, max 12h). Hand the returned token to whatever tool needs narrow access, as BROODS_SESSION_TOKEN. It is shown once and is not stored here.",inputSchema:{roleId:e().min(1),ttlSeconds:o().int().positive().max(43200).optional()}},async({roleId:i,ttlSeconds:c})=>await d(async()=>await r.assumeRole(i,c===void 0?{}:{ttlSeconds:c}))),t.registerTool("update-account",{description:"Rename this account or change its description. Everything else about an account is derived, not settable.",inputSchema:{username:e().optional(),description:e().nullable().optional()}},async({username:i,description:c})=>await d(async()=>await r.updateAccount({...i===void 0?{}:{username:i},...c===void 0?{}:{description:c}}))),t.registerTool("get-account",{description:"The account this server's credential resolves to. Run it first to confirm which tenant you are about to change.",inputSchema:{}},async()=>await d(async()=>await r.getAccount()))}function x(t,r,n,i){let c=e().min(1).describe(`The ${n.key}.`),p=n.scoped?` ${n.plural} live in one stage, so this also takes 'project' and 'stage'.`:"",{list:f,get:g,create:y,update:S,remove:_}=n;if(f){let u=`List every ${n.singular} on the account.${p}`;if(n.scoped)t.registerTool(`list-${n.plural}`,{description:u,inputSchema:E},async({project:h,stage:m})=>await d(async()=>await f(r,T(n,i,h,m))));else t.registerTool(`list-${n.plural}`,{description:u,inputSchema:{}},async()=>await d(async()=>await f(r)))}if(g)t.registerTool(`get-${n.singular}`,{description:`Read one ${n.singular} by ${n.key}.`,inputSchema:{id:c}},async({id:u})=>await d(async()=>await g(r,u)));if(y){let u=`Create one ${n.singular}. 'body' is the request body the config plane documents.`+(n.createHint?` ${n.createHint}`:"")+p+" Prefer changing the broods/ manifest and deploying for anything the project already declares.",h=s(e(),l());if(n.scoped)t.registerTool(`create-${n.singular}`,{description:u,inputSchema:{body:h,...E}},async({body:m,project:I,stage:C})=>await d(async()=>await y(r,m,T(n,i,I,C))));else t.registerTool(`create-${n.singular}`,{description:u,inputSchema:{body:h}},async({body:m})=>await d(async()=>await y(r,m)))}if(S)t.registerTool(`update-${n.singular}`,{description:`Deep-merge a patch into one ${n.singular} and return the updated record, so there is no need to read it back.`+(n.updateHint?` ${n.updateHint}`:""),inputSchema:{id:c,body:s(e(),l())}},async({id:u,body:h})=>await d(async()=>await S(r,u,h)));if(_)t.registerTool(`delete-${n.singular}`,{description:`Delete one ${n.singular}. Requires confirm:true, and takes one ${n.key} per call: never loop this over a list.`+(n.deleteHint?` ${n.deleteHint}`:""),inputSchema:{id:c,confirm:v}},async({id:u,confirm:h})=>await d(async()=>(w(h,`Deleting ${n.singular} '${u}' goes away for good: name it, get the owner's agreement, then retry.`),{deleted:await _(r,u),id:u})))}export{Pt as createBroodsMcpServer};