broods 0.30.0 → 0.32.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
@@ -101,6 +101,20 @@ declare const MODEL_PROVIDERS: {
101
101
  };
102
102
  type AccountModelProviderName = keyof typeof MODEL_PROVIDERS;
103
103
 
104
+ /**
105
+ * OAuth 2.0 refresh-token grant for an external row. Core mints access tokens
106
+ * at connect time and sends `Authorization: Bearer <token>`, so a server
107
+ * whose tokens expire (Google's Workspace MCP endpoints) still works where a
108
+ * static header cannot. Secret fields hold ${NAME} refs on the row.
109
+ */
110
+ interface McpOauth {
111
+ clientId: string;
112
+ clientSecret: string;
113
+ refreshToken: string;
114
+ /** Token endpoint, https only; core defaults to https://oauth2.googleapis.com/token. */
115
+ tokenUrl?: string;
116
+ }
117
+
104
118
  /**
105
119
  * Agent configuration: types for the per-agent settings object, input
106
120
  * normalization, encryption helpers, patch-merge, and redaction.
@@ -193,6 +207,11 @@ interface AgentSubagentConfig {
193
207
  interface AgentModelConfig extends LanguageModelCallOptions, Pick<RequestOptions, "maxRetries" | "timeout"> {
194
208
  provider?: AccountModelProviderName;
195
209
  modelId?: string;
210
+ /**
211
+ * Speech-to-text model for inbound audio, on the same provider and key as
212
+ * `modelId`. Defaults to the widest-container model the provider ships.
213
+ */
214
+ transcriptionModelId?: string;
196
215
  providerOptions?: AgentModelProviderOptions;
197
216
  output?: AgentModelOutputConfig;
198
217
  }
@@ -294,6 +313,12 @@ interface AgentMcpEntry {
294
313
  needsApproval?: boolean;
295
314
  /** Extra request headers; values resolved from account env vars at sync. */
296
315
  headers?: Record<string, string>;
316
+ /**
317
+ * Overrides for the row's oauth credentials; values resolved from account
318
+ * env vars at sync, so the row's ${NAME} refs never reach the token
319
+ * endpoint. tokenUrl stays on the row, where registration checked it.
320
+ */
321
+ oauth?: Partial<Omit<McpOauth, "tokenUrl">>;
297
322
  [key: string]: unknown;
298
323
  }
299
324
  interface AgentChannelsConfig {
@@ -496,14 +521,6 @@ interface SandboxConfig {
496
521
  options?: Record<string, unknown>;
497
522
  }
498
523
 
499
- /**
500
- * Workspace-config validation for the Convex config plane. Ports core's
501
- * former storage/workspace-config.ts normalizer so the public /v1/workspaces
502
- * contract is unchanged. Workspace config holds no secrets (a roleArn is not
503
- * a secret), so it is stored and returned in plaintext. Pure module — safe
504
- * for the default Convex runtime. The public projection lives in
505
- * ./responses.ts.
506
- */
507
524
  declare const WORKSPACE_STORAGE_PROVIDERS: readonly ["s3"];
508
525
  type WorkspaceStorageProvider = (typeof WORKSPACE_STORAGE_PROVIDERS)[number];
509
526
  type WorkspaceStorageAuth = {
@@ -611,6 +628,7 @@ type ChannelReplyIn = (typeof CHANNEL_REPLY_TARGETS)[number];
611
628
 
612
629
  interface TelegramSource {
613
630
  chatId: number;
631
+ commandToken?: string;
614
632
  messageId: string;
615
633
  messageThreadId?: number;
616
634
  threadId: string;
@@ -1013,6 +1031,7 @@ type ObservabilitySubscribeMessage = {
1013
1031
  backfill?: number;
1014
1032
  liveOnly?: boolean;
1015
1033
  minLevel?: LogLevel;
1034
+ sandboxId?: string;
1016
1035
  };
1017
1036
  type ObservabilityUnsubscribeMessage = {
1018
1037
  type: "unsubscribe";
@@ -1045,6 +1064,11 @@ declare function isObservabilityClientMessage(v: unknown): v is ObservabilityCli
1045
1064
  declare function isLogLevel(value: unknown): value is LogLevel;
1046
1065
  /** Whether a span is a top-level run, each of which owns its own trace. */
1047
1066
  declare function isRootSpanKind(kind: ObservabilitySpanRow["kind"]): boolean;
1067
+ /**
1068
+ * Narrow a wire value to a sandbox log id. Strict on purpose: the gateway
1069
+ * interpolates it into LogQL, so only the UUID shape core mints may pass.
1070
+ */
1071
+ declare function isSandboxLogId(value: unknown): value is string;
1048
1072
 
1049
1073
  /**
1050
1074
  * Configurable client for running deployed agents over direct core SSE.
@@ -1403,6 +1427,18 @@ interface StageScope {
1403
1427
  project: string;
1404
1428
  stage: string;
1405
1429
  }
1430
+ /**
1431
+ * OAuth 2.0 refresh-token grant on an external MCP row. The runtime mints and
1432
+ * refreshes access tokens and sends `Authorization: Bearer <token>` itself.
1433
+ * `clientSecret` and `refreshToken` must be `${NAME}` account env refs;
1434
+ * `tokenUrl` defaults to https://oauth2.googleapis.com/token.
1435
+ */
1436
+ interface McpOauthInput {
1437
+ clientId: string;
1438
+ clientSecret: string;
1439
+ refreshToken: string;
1440
+ tokenUrl?: string;
1441
+ }
1406
1442
  /** Public MCP server registration returned by the `/v1/mcp` routes (#331). */
1407
1443
  interface AccountMcp {
1408
1444
  accountId: string;
@@ -1417,6 +1453,7 @@ interface AccountMcp {
1417
1453
  /** Hosted servers only: content hash of the uploaded bundle. */
1418
1454
  sha256?: string;
1419
1455
  headers?: Record<string, string>;
1456
+ oauth?: McpOauthInput;
1420
1457
  allowedTools?: string[];
1421
1458
  disabled: boolean;
1422
1459
  status: string;
@@ -1436,6 +1473,7 @@ interface CreateMcpInput {
1436
1473
  bundleStorageId?: string;
1437
1474
  sha256?: string;
1438
1475
  headers?: Record<string, string>;
1476
+ oauth?: McpOauthInput;
1439
1477
  allowedTools?: string[];
1440
1478
  }
1441
1479
  /** Fields accepted by `PATCH /v1/mcp/{serverId}`; every field is optional. */
@@ -1447,6 +1485,7 @@ interface UpdateMcpInput {
1447
1485
  bundleStorageId?: string;
1448
1486
  sha256?: string;
1449
1487
  headers?: Record<string, string>;
1488
+ oauth?: McpOauthInput;
1450
1489
  allowedTools?: string[];
1451
1490
  disabled?: boolean;
1452
1491
  }
@@ -1756,7 +1795,7 @@ interface BroodsWebSocketClientOptions {
1756
1795
  connectTimeoutMs?: number;
1757
1796
  }
1758
1797
  interface WebSocketConstructorLike {
1759
- new (url: string): WebSocketLike;
1798
+ new (url: string, protocols?: string[]): WebSocketLike;
1760
1799
  }
1761
1800
  interface WebSocketLike {
1762
1801
  readyState: number;
@@ -1785,6 +1824,13 @@ declare class BroodsWebSocketClient {
1785
1824
  buildUrl(input: Pick<WebSocketRunInput, "agent" | "endpointId" | "projectSlug" | "stageSlug">): string;
1786
1825
  private resolveWebSocket;
1787
1826
  }
1827
+ /**
1828
+ * The credential travels as a `Sec-WebSocket-Protocol` entry rather than in
1829
+ * the URL, so it never lands in proxy or access logs. The gateway answers
1830
+ * with `broods.v1`, which is what completes a handshake that offered
1831
+ * subprotocols.
1832
+ */
1833
+ declare function webSocketSubprotocols(apiKey: string): string[];
1788
1834
 
1789
1835
  declare function toWebSocketBaseUrl(url: string): string;
1790
1836
 
@@ -1898,7 +1944,7 @@ interface McpDefinitionConfig {
1898
1944
  * Hosted alternative to `url`: declare the server inline —
1899
1945
  * `handler: createMcpHandler(...)` from @modelcontextprotocol/server,
1900
1946
  * right next to the `defineMcp` call. The CLI bundles the defining module
1901
- * and the tool-runner Lambda hosts it, one invoke per request.
1947
+ * and the tool-runner Lambda hosts it, one invoke per batch of requests.
1902
1948
  */
1903
1949
  handler?: McpHandler;
1904
1950
  /**
@@ -1907,6 +1953,20 @@ interface McpDefinitionConfig {
1907
1953
  * `Bearer ${env("TOKEN")}` — never carry an inline secret.
1908
1954
  */
1909
1955
  headers?: Record<string, string>;
1956
+ /**
1957
+ * OAuth 2.0 refresh-token grant for an external server whose access tokens
1958
+ * expire (Google's Workspace MCP endpoints). The runtime mints, caches and
1959
+ * refreshes access tokens and sends `Authorization: Bearer <token>` itself,
1960
+ * so do not also set an Authorization header. `clientSecret` and
1961
+ * `refreshToken` must be `env("NAME")` refs; `tokenUrl` defaults to
1962
+ * https://oauth2.googleapis.com/token.
1963
+ */
1964
+ oauth?: {
1965
+ clientId: string | EnvRef;
1966
+ clientSecret: string | EnvRef;
1967
+ refreshToken: string | EnvRef;
1968
+ tokenUrl?: string;
1969
+ };
1910
1970
  /** Tool names agents may use from this server; omit to allow all. */
1911
1971
  allowedTools?: string[];
1912
1972
  }
@@ -2297,5 +2357,5 @@ declare function isResource(value: unknown): value is AnyResource;
2297
2357
  declare function isConnectionDefinition(value: unknown): value is AnyConnectionDefinition;
2298
2358
  declare function isBroodsConfig(value: unknown): value is BroodsConfigDefinition;
2299
2359
 
2300
- export { BroodsAccountApiError, BroodsAccountClient, BroodsClient, BroodsWebSocketClient, DEFAULT_CORE_BASE_URL, IngressAcceptedError, MAX_OBSERVABILITY_BACKFILL, BroodsWebSocketClient as WebSocketClient, BroodsWebSocketClient as WebsocketClient, defineAgent, defineBroods, defineCron, defineDiscordChannel, defineDiscordConnection, defineGitHubChannel, defineGitHubConnection, defineHarness, defineMcp, definePancakeChannel, definePancakeConnection, definePolicy, defineSandbox, defineSkill, defineSlackChannel, defineSlackConnection, defineTelegramChannel, defineTelegramConnection, defineWorkspace, defineZaloChannel, defineZaloConnection, env, envPlaceholder, isBroodsConfig, isConnectionDefinition, isLogLevel, isObservabilityClientMessage, isResource, isRootSpanKind, normalizeHttpServiceUrl, readSseStream, resolveEnvCredential, resolveRunEvents, toWebSocketBaseUrl };
2301
- export type { Account, AccountAgent, AccountChannel, AccountEnvVar, AccountMcp, AccountPolicy, AccountRole, AccountSandbox, AccountWorkspace, Agent, AgentChannelsConfig, AgentCodeHookConfig, AgentConfig, AgentConfigDoc, AgentDefinitionConfig, AgentDiscordChannelConfig, AgentGitHubChannelConfig, AgentHandle, AgentHookEventName, AgentHooks, AgentHooksConfig, AgentPancakeChannelConfig, AgentProviderSettings, AgentReference, AgentResource, AgentRunEventInput, AgentRunInput, AgentRunModelOverrides, AgentRunOverrides, AgentRunResult, AgentSkillsDefinitionConfig, AgentSlackChannelConfig, AgentStreamPart, AgentSubagentDefinitionConfig, AgentTelegramChannelConfig, AgentWebhookHookConfig, AgentWorkspaceInput, AgentWorkspaceRef, AgentWorkspaceRefInput, AgentZaloChannelConfig, AnyConnectionDefinition, AnyResource, AssumeRoleResult, AsyncAgentRun, AsyncPollOptions, AsyncRequestAccepted, AsyncStatus, BroodsAccount, BroodsAccountClientOptions, BroodsClientOptions, BroodsConfigDefinition, BroodsProjectConfig, BroodsWebSocketClientOptions, ChannelAgentInput, ChannelDefinitionConfig, ChannelMessageReceived, ChannelPartition, ChannelRecordConfig, ChannelReference, ChannelReplyIn, ChannelResource, ChannelType, CliManifest, CliManifestResource, ConnectionDefinition, CreateAgentResult, CreateClientCronInput, CreateCronInput, CreateMcpInput, Cron, CronDefinitionConfig, CronDoc, CronLastStatus, CronResource, CronRun, CronStatus, DeleteAccountResult, DiscordChannelInput, DiscordConnectionDefinition, DiscordConnectionInput, DiscordMessageSource, DiscordSource, Doc, EnvAccessor, EnvRef, EnvRefString, GeneratedIds, GitHubChannelInput, GitHubConnectionDefinition, GitHubConnectionInput, GitHubMessageSource, GitHubSource, HarnessDefinition, HarnessType, HookContext, Id, IngressMode, IngressStatus, LogLevel, McpDefinitionConfig, McpHandler, McpResource, ObservabilityBackfillMessage, ObservabilityClientMessage, ObservabilityErrorMessage, ObservabilityLogEntry, ObservabilityLogMessage, ObservabilityReadyMessage, ObservabilityServerMessage, ObservabilitySpanMessage, ObservabilitySpanRow, ObservabilitySubscribeMessage, ObservabilityUnsubscribeMessage, PancakeChannelInput, PancakeConnectionDefinition, PancakeConnectionInput, PancakeMessageSource, PancakeSource, PolicyDefinitionConfig, PolicyDocument, PolicyResource, ProjectDoc, ProviderConfigInput, ProviderSettingsInput, ResourceApi, ResourceDefinition, ResourceInput, ResourceKind, RotateSecretResult, Sandbox, SandboxConfig, SandboxConfigDoc, SandboxDefinitionConfig, SandboxDefinitionOptions, SandboxLifecycleResult, SandboxResource, SandboxSnapshotResult, SandboxTerminalTicket, Skill, SkillDefinitionConfig, SkillResource, SkillUploadInput, SlackChannelInput, SlackConnectionDefinition, SlackConnectionInput, SlackMessageSource, SlackSource, StageDoc, StageScope, TelegramChannelInput, TelegramConnectionDefinition, TelegramConnectionInput, TelegramMessageSource, TelegramSource, ToolApprovalSummary, UpdateAgentInput, UpdateCronInput, UpdateMcpInput, WebSocketAttachInput, WebSocketClientAttachMessage, WebSocketClientCancelMessage, WebSocketClientControlMessage, WebSocketClientExecuteMessage, WebSocketClientMessage, WebSocketConstructorLike, WebSocketHandlers, WebSocketLike, WebSocketOutputMessage, WebSocketRunInput, WebSocketServerMessage, WebSocketStreamMessage, WebSocketSubscription, Workspace, WorkspaceConfig, WorkspaceConfigDoc, WorkspaceDefinitionConfig, WorkspaceFileEntry, WorkspaceResource, ZaloChannelInput, ZaloConnectionDefinition, ZaloConnectionInput, ZaloMessageSource, ZaloSource };
2360
+ export { BroodsAccountApiError, BroodsAccountClient, BroodsClient, BroodsWebSocketClient, DEFAULT_CORE_BASE_URL, IngressAcceptedError, MAX_OBSERVABILITY_BACKFILL, BroodsWebSocketClient as WebSocketClient, BroodsWebSocketClient as WebsocketClient, defineAgent, defineBroods, defineCron, defineDiscordChannel, defineDiscordConnection, defineGitHubChannel, defineGitHubConnection, defineHarness, defineMcp, definePancakeChannel, definePancakeConnection, definePolicy, defineSandbox, defineSkill, defineSlackChannel, defineSlackConnection, defineTelegramChannel, defineTelegramConnection, defineWorkspace, defineZaloChannel, defineZaloConnection, env, envPlaceholder, isBroodsConfig, isConnectionDefinition, isLogLevel, isObservabilityClientMessage, isResource, isRootSpanKind, isSandboxLogId, normalizeHttpServiceUrl, readSseStream, resolveEnvCredential, resolveRunEvents, toWebSocketBaseUrl, webSocketSubprotocols };
2361
+ export type { Account, AccountAgent, AccountChannel, AccountEnvVar, AccountMcp, AccountPolicy, AccountRole, AccountSandbox, AccountWorkspace, Agent, AgentChannelsConfig, AgentCodeHookConfig, AgentConfig, AgentConfigDoc, AgentDefinitionConfig, AgentDiscordChannelConfig, AgentGitHubChannelConfig, AgentHandle, AgentHookEventName, AgentHooks, AgentHooksConfig, AgentPancakeChannelConfig, AgentProviderSettings, AgentReference, AgentResource, AgentRunEventInput, AgentRunInput, AgentRunModelOverrides, AgentRunOverrides, AgentRunResult, AgentSkillsDefinitionConfig, AgentSlackChannelConfig, AgentStreamPart, AgentSubagentDefinitionConfig, AgentTelegramChannelConfig, AgentWebhookHookConfig, AgentWorkspaceInput, AgentWorkspaceRef, AgentWorkspaceRefInput, AgentZaloChannelConfig, AnyConnectionDefinition, AnyResource, AssumeRoleResult, AsyncAgentRun, AsyncPollOptions, AsyncRequestAccepted, AsyncStatus, BroodsAccount, BroodsAccountClientOptions, BroodsClientOptions, BroodsConfigDefinition, BroodsProjectConfig, BroodsWebSocketClientOptions, ChannelAgentInput, ChannelDefinitionConfig, ChannelMessageReceived, ChannelPartition, ChannelRecordConfig, ChannelReference, ChannelReplyIn, ChannelResource, ChannelType, CliManifest, CliManifestResource, ConnectionDefinition, CreateAgentResult, CreateClientCronInput, CreateCronInput, CreateMcpInput, Cron, CronDefinitionConfig, CronDoc, CronLastStatus, CronResource, CronRun, CronStatus, DeleteAccountResult, DiscordChannelInput, DiscordConnectionDefinition, DiscordConnectionInput, DiscordMessageSource, DiscordSource, Doc, EnvAccessor, EnvRef, EnvRefString, GeneratedIds, GitHubChannelInput, GitHubConnectionDefinition, GitHubConnectionInput, GitHubMessageSource, GitHubSource, HarnessDefinition, HarnessType, HookContext, Id, IngressMode, IngressStatus, LogLevel, McpDefinitionConfig, McpHandler, McpOauthInput, McpResource, ObservabilityBackfillMessage, ObservabilityClientMessage, ObservabilityErrorMessage, ObservabilityLogEntry, ObservabilityLogMessage, ObservabilityReadyMessage, ObservabilityServerMessage, ObservabilitySpanMessage, ObservabilitySpanRow, ObservabilitySubscribeMessage, ObservabilityUnsubscribeMessage, PancakeChannelInput, PancakeConnectionDefinition, PancakeConnectionInput, PancakeMessageSource, PancakeSource, PolicyDefinitionConfig, PolicyDocument, PolicyResource, ProjectDoc, ProviderConfigInput, ProviderSettingsInput, ResourceApi, ResourceDefinition, ResourceInput, ResourceKind, RotateSecretResult, Sandbox, SandboxConfig, SandboxConfigDoc, SandboxDefinitionConfig, SandboxDefinitionOptions, SandboxLifecycleResult, SandboxResource, SandboxSnapshotResult, SandboxTerminalTicket, Skill, SkillDefinitionConfig, SkillResource, SkillUploadInput, SlackChannelInput, SlackConnectionDefinition, SlackConnectionInput, SlackMessageSource, SlackSource, StageDoc, StageScope, TelegramChannelInput, TelegramConnectionDefinition, TelegramConnectionInput, TelegramMessageSource, TelegramSource, ToolApprovalSummary, UpdateAgentInput, UpdateCronInput, UpdateMcpInput, WebSocketAttachInput, WebSocketClientAttachMessage, WebSocketClientCancelMessage, WebSocketClientControlMessage, WebSocketClientExecuteMessage, WebSocketClientMessage, WebSocketConstructorLike, WebSocketHandlers, WebSocketLike, WebSocketOutputMessage, WebSocketRunInput, WebSocketServerMessage, WebSocketStreamMessage, WebSocketSubscription, Workspace, WorkspaceConfig, WorkspaceConfigDoc, WorkspaceDefinitionConfig, WorkspaceFileEntry, WorkspaceResource, ZaloChannelInput, ZaloConnectionDefinition, ZaloConnectionInput, ZaloMessageSource, ZaloSource };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{A as H,B as K,C as j,D as G,E as F,F as z,G as Z,H as V,I as X,J as Y,K as J,L as Q,M as ee,N as te,O as re,P as ne,Q as se,a as v,b as S,m as k,n as A,o as M,p as h,q as w,r as E,s as D,t as T,u as q,v as N,w as _,x as P,y as U,z as B}from"./chunk-3qpgf0c1.js";import{R as O,S as R,T as L,U as W}from"./chunk-yy11cxjg.js";import"./chunk-rx5qcgbh.js";var a=500;function i(e){if(typeof e!=="object"||e===null)return!1;let t=e;if(t.type==="subscribe"){let r=t.stream;if(r!=="logs"&&r!=="traces")return!1;let n=t.backfill;if(n!==void 0&&(typeof n!=="number"||!Number.isSafeInteger(n)||n<0||n>500))return!1;if(t.liveOnly!==void 0&&typeof t.liveOnly!=="boolean")return!1;let s=t.minLevel;if(s!==void 0&&!o(s))return!1;return!0}if(t.type==="unsubscribe"){let r=t.stream;return r==="logs"||r==="traces"}return!1}function o(e){return e==="DEBUG"||e==="INFO"||e==="WARN"||e==="ERROR"}function p(e){return e==="task"||e==="cron"||e==="subtask"}export{R as BroodsAccountApiError,W as BroodsAccountClient,M as BroodsClient,w as BroodsWebSocketClient,k as DEFAULT_CORE_BASE_URL,A as IngressAcceptedError,a as MAX_OBSERVABILITY_BACKFILL,w as WebSocketClient,w as WebsocketClient,Z as defineAgent,z as defineBroods,te as defineCron,B as defineDiscordChannel,T as defineDiscordConnection,H as defineGitHubChannel,q as defineGitHubConnection,V as defineHarness,Q as defineMcp,K as definePancakeChannel,N as definePancakeConnection,ee as definePolicy,Y as defineSandbox,J as defineSkill,j as defineSlackChannel,_ as defineSlackConnection,G as defineTelegramChannel,P as defineTelegramConnection,X as defineWorkspace,F as defineZaloChannel,U as defineZaloConnection,D as env,O as envPlaceholder,se as isBroodsConfig,ne as isConnectionDefinition,o as isLogLevel,i as isObservabilityClientMessage,re as isResource,p as isRootSpanKind,h as normalizeHttpServiceUrl,S as readSseStream,L as resolveEnvCredential,v as resolveRunEvents,E as toWebSocketBaseUrl};
1
+ import{A as R,B as P,C as T,D as E,E as H,F as _,G as N,H as U,I as j,J as K,K as L,L as G,M as O,N as z,O as Z,P as B,Q as F,R as J,S as Q,T as V,U as X,V as Y,W as ee,a as d,b as l,c as u,d as C,e as f,f as m,g as y,r as x,s as I,t as S,u as k,v as M,w as W,x as D,y as w,z as q}from"./chunk-h9meaxpn.js";import{X as A,Y as h,Z as b,_ as v}from"./chunk-zk74tvhq.js";import"./chunk-7qxgm62s.js";export{h as BroodsAccountApiError,v as BroodsAccountClient,S as BroodsClient,M as BroodsWebSocketClient,x as DEFAULT_CORE_BASE_URL,I as IngressAcceptedError,u as MAX_OBSERVABILITY_BACKFILL,M as WebSocketClient,M as WebsocketClient,O as defineAgent,G as defineBroods,V as defineCron,_ as defineDiscordChannel,q as defineDiscordConnection,N as defineGitHubChannel,R as defineGitHubConnection,z as defineHarness,J as defineMcp,U as definePancakeChannel,P as definePancakeConnection,Q as definePolicy,B as defineSandbox,F as defineSkill,j as defineSlackChannel,T as defineSlackConnection,K as defineTelegramChannel,E as defineTelegramConnection,Z as defineWorkspace,L as defineZaloChannel,H as defineZaloConnection,w as env,A as envPlaceholder,ee as isBroodsConfig,Y as isConnectionDefinition,f as isLogLevel,C as isObservabilityClientMessage,X as isResource,m as isRootSpanKind,y as isSandboxLogId,k as normalizeHttpServiceUrl,l as readSseStream,b as resolveEnvCredential,d as resolveRunEvents,D as toWebSocketBaseUrl,W as webSocketSubprotocols};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "broods",
3
- "version": "0.30.0",
3
+ "version": "0.32.0",
4
4
  "description": "CLI + TypeScript SDK for the broods agent platform.",
5
5
  "keywords": [
6
6
  "agents",
@@ -59,7 +59,7 @@
59
59
  "zod": "^4.4.3"
60
60
  },
61
61
  "devDependencies": {
62
- "@ai-sdk/tui": "1.0.78",
62
+ "@ai-sdk/tui": "1.0.88",
63
63
  "@arethetypeswrong/cli": "^0.18.5",
64
64
  "@chat-adapter/discord": "^4.38.1",
65
65
  "@chat-adapter/github": "^4.38.1",
@@ -68,14 +68,14 @@
68
68
  "@modelcontextprotocol/client": "^2.0.0",
69
69
  "@types/bun": "^1.3.14",
70
70
  "@typescript/typescript6": "6.0.2",
71
- "ai": "^7.0.77",
71
+ "ai": "^7.0.87",
72
72
  "publint": "^0.3.23",
73
73
  "rollup": "^4.62.4",
74
74
  "rollup-plugin-dts": "^6.5.1",
75
75
  "typescript": "^7.0.2"
76
76
  },
77
77
  "peerDependencies": {
78
- "ai": "^7.0.77"
78
+ "ai": "^7.0.87"
79
79
  },
80
80
  "engines": {
81
81
  "node": ">=22.15"
@@ -1,5 +0,0 @@
1
- function k(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*D(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 Q,readFile as ee,writeFile as ne}from"node:fs/promises";import{homedir as te}from"node:os";import{dirname as oe,join as re}from"node:path";var Ee="broods",De="_generated",h=re(te(),".broods","config.json"),N="broods.app",O="dashboard",se="gateway";async function Ne(){let e=process.env.BROODS_TOKEN,n=process.env.BROODS_BASE_URL;if(e&&n)return{baseUrl:d(n),token:e,createdAt:new Date().toISOString()};try{let t=JSON.parse(await ee(h,"utf8"));if(typeof t.baseUrl!=="string"||!t.baseUrl)return null;return t}catch{return null}}async function Oe(e){await Q(oe(h),{recursive:!0}),await ne(h,`${JSON.stringify(e,null,2)}
3
- `,"utf8")}function T(){return process.env.BROODS_STAGE}function d(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(`${O}.`))return;let t=n.hostname.slice(O.length+1);if(t!==N&&!t.endsWith(`.${N}`))return;return n.hostname=`${se}.${t}`,d(n.origin)}catch{return}}import{existsSync as U,readFileSync as E,statSync as ie}from"node:fs";import{join as W,resolve as M}from"node:path";var v=new Map,ae=new Set(Object.keys(process.env)),P=new Set;function I(e=process.cwd()){ce(e);let n=de();return{dashboardUrl:process.env.BROODS_DASHBOARD_URL??n?.dashboardUrl,baseUrl:process.env.BROODS_BASE_URL??n?.baseUrl,token:process.env.BROODS_TOKEN??n?.token,project:process.env.BROODS_PROJECT,stage:T()}}function $e(e,n=process.cwd()){let t=process.env[e];if(t===void 0)return!1;let o=M(n);for(let r of[".env.local",".env"]){let s=W(o,r);if(!U(s))continue;let i=_(E(s,"utf8"));if(i[e]!==void 0)return i[e]!==t}return!0}function ce(e){let n=M(e),t=process.env.BROODS_RELOAD_ENV==="1";for(let o of[".env",".env.local"]){let r=W(n,o);if(!U(r)){v.delete(r);continue}let s=ie(r).mtimeMs,i=v.get(r);if(i&&i.mtimeMs===s)continue;v.set(r,{mtimeMs:s});for(let[a,u]of Object.entries(_(E(r,"utf8"))))if(t||!ae.has(a)||P.has(a))process.env[a]=u,P.add(a)}}function _(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]=ue(r.slice(s+1).trim())}return n}function ue(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 de(){try{let e=JSON.parse(E(h,"utf8"));if(typeof e.baseUrl!=="string"||typeof e.token!=="string")return null;return{baseUrl:d(e.baseUrl),...typeof e.dashboardUrl==="string"?{dashboardUrl:d(e.dashboardUrl)}:{},token:e.token}}catch{return null}}var x="https://gateway.broods.app";class B 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={}){I(),this.baseUrl=A(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||x),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("/")}`}stageWebhookUrl(e,n,t){let o=[e,"dev",n,t].map(encodeURIComponent);return`${this.baseUrl}/webhooks/${o.join("/")}`}agent(e,n){if(typeof e==="string"){let o=e,r=n??"";if(!r)throw Error(`Agent ${o} is missing a generated id. Run broods dev --once or broods deploy to sync it first.`);return{id:r,run:(s)=>this.run({...s,agentName:o,agentId:r}),runAsync:(s)=>this.runAsync({...s,agentName:o,agentId:r}),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=K(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 B(H(await s.json(),o));if(!s.body)throw Error("Run response has no body");for await(let i of D(s.body)){let a;try{a=JSON.parse(i)}catch{continue}if(a.type==="error")throw Error(`Agent run failed: ${he(a.error)}`);yield a}}async runAsync(e,n){let t=n?{...n,agentId:e.id,agentName:e.name}:e,o=K(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 fe(s,"202 JSON")}`);let i=H(await s.json(),o);return{...i,conversationKey:o.conversationKey,poll:()=>this.getAsyncStatus(i),wait:(a)=>this.waitForAsyncStatus(i,a)}}async getAsyncStatus(e,n={}){let t=this.resolveStatusUrl(e,n),o=await this.fetchJson(t,{method:"GET",headers:this.apiKeyHeaders()});if(o.status===404)return{status:"not_found"};if(!o.ok)throw Error(`Status check failed: ${o.status} ${await o.text()}`);return await o.json()}async waitForAsyncStatus(e,n={}){let t=Date.now()+(n.timeoutMs??180000),o=n.intervalMs??2000;while(Date.now()<t){if(n.signal?.aborted)throw Error("Async status polling aborted.");let r=await this.getAsyncStatus(e,n);if(r.status==="awaiting_approval"||r.status==="completed"||r.status==="failed"||r.status==="expired"||r.status==="not_found")return r;await ye(o,n.signal)}throw Error("Polling timeout")}async createCron(e){let n=await this.fetchJson(`${this.baseUrl}/v1/crons`,{method:"POST",headers:this.apiKeyHeaders(),body:JSON.stringify(me(e))});if(n.status!==201)throw Error(`Create cron job failed: ${n.status} ${await p(n)}`);return await n.json()}async listCrons(){let e=await this.fetchJson(`${this.baseUrl}/v1/crons`,{method:"GET",headers:this.apiKeyHeaders()});if(!e.ok)throw Error(`List cron jobs failed: ${e.status} ${await p(e)}`);return(await e.json()).crons}async getCron(e){let n=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}`,{method:"GET",headers:this.apiKeyHeaders()});if(n.status===404)return null;if(!n.ok)throw Error(`Get cron job failed: ${n.status} ${await p(n)}`);return await n.json()}async listCronRuns(e,n={}){let t=new URLSearchParams;if(n.limit!==void 0)t.set("limit",String(n.limit));let o=t.size>0?`?${t}`:"",r=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}/runs${o}`,{method:"GET",headers:this.apiKeyHeaders()});if(!r.ok)throw Error(`List cron job runs failed: ${r.status} ${await p(r)}`);return(await r.json()).runs}async updateCron(e,n){let t=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}`,{method:"PATCH",headers:this.apiKeyHeaders(),body:JSON.stringify(n)});if(!t.ok)throw Error(`Update cron job failed: ${t.status} ${await p(t)}`);return await t.json()}async deleteCron(e){let n=await this.fetchJson(`${this.baseUrl}/v1/crons/${encodeURIComponent(e)}`,{method:"DELETE",headers:this.apiKeyHeaders()});if(n.status===404)return!1;if(!n.ok)throw Error(`Delete cron job failed: ${n.status} ${await p(n)}`);return(await n.json()).deleted}scopedUrl(e,n=""){if(e.projectSlug&&e.stageSlug&&e.endpointId)return`${this.baseUrl}/v1/${encodeURIComponent(e.projectSlug)}/agents/${encodeURIComponent(e.stageSlug)}/${encodeURIComponent(e.endpointId)}${n}`;return`${this.baseUrl}${n}`}async openStream(e,n){if(this.apiKey)return await this.fetchCore(e,n,{Authorization:`Bearer ${this.apiKey}`});throw Error(`BroodsClient streams directly from the core service at ${this.baseUrl}. Provide apiKey. For a self-hosted core service, set host/baseUrl or BROODS_HOST/BROODS_BASE_URL.`)}async fetchCore(e,n,t){try{return await this.fetchImpl(n,{method:"POST",headers:{"Content-Type":"application/json",Accept:"text/event-stream",...t},body:JSON.stringify(e)})}catch(o){throw Error(`Cannot access the broods core service at ${n}. The SDK uses ${x} 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 pe(this.baseUrl,e,n.agentId)}}function A(e){let n=e.trim(),t=/^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(n)?n:`https://${n}`;return d(t)}function K(e,n){let t=e.eventId??`${n}-${Date.now()}`;return{agentId:e.agentId,eventId:t,conversationKey:e.conversationKey??t,events:k(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 H(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 pe(e,n,t){return`${A(e)}/status/${encodeURIComponent(n)}?agentId=${encodeURIComponent(t)}`}async function fe(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 me(e){if("agentId"in e)return e;let n=e.agent,t=typeof n==="string"?n:n.id,{agent:o,...r}=e;return{...r,agentId:t}}function ye(e,n){return new Promise((t,o)=>{if(n?.aborted){o(Error("Async status polling aborted."));return}let r=setTimeout(t,e);n?.addEventListener("abort",()=>{clearTimeout(r),o(Error("Async status polling aborted."))},{once:!0})})}function he(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 Ce=2000,j=0,C=1;class Se{baseUrl;apiKey;WebSocketImpl;connectTimeoutMs;constructor(e={}){if(I(),this.baseUrl=F(e.baseUrl||e.host||process.env.BROODS_BASE_URL||process.env.BROODS_HOST||x),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??Ce}subscribe(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=Re(e),s=L(this.baseUrl),i=new t(o),a=!1,u=!1,l=setTimeout(()=>{if(!a)y(s)},this.connectTimeoutMs),w=(c=1000,R="client closed")=>{if(u)return;if(u=!0,clearTimeout(l),e.signal?.removeEventListener("abort",S),i.readyState===C||i.readyState===j)i.close(c,R)},y=(c)=>{n.onError?.(c),w(1011,"websocket error")},X=()=>{n.onDone?.(),w(1000,"done")},S=()=>{if(i.readyState===C)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(l),e.signal?.aborted){S();return}i.send(JSON.stringify({type:"execute",agentId:r,events:k(e),sessionId:e.sessionId,...e.eventId!==void 0?{eventId:e.eventId}:{},...e.mode!==void 0?{mode:e.mode}:{},...e.idempotencyKey!==void 0?{idempotencyKey:e.idempotencyKey}:{},...e.system!==void 0?{system:e.system}:{},...e.model!==void 0?{model:e.model}:{}}))},i.onmessage=(c)=>{if(typeof c.data!=="string")return;let R=q(c.data);if(!R)return;let b=G(R,n);switch(n.onMessage?.(b),b.type){case"meta":n.onMeta?.(b);break;case"done":X();break;case"error":y(Error(J(b.error)));break}},i.onerror=()=>{y(s)},i.onclose=(c)=>{if(clearTimeout(l),e.signal?.removeEventListener("abort",S),u||c.code===1000)return;y(Error(c.reason||"WebSocket connection closed."))},{url:o,sendControl:function(c){if(i.readyState!==C)throw Error("WebSocket is not open");i.send(JSON.stringify({type:"control",...c}))},close:w}}attach(e,n={}){let t=this.resolveWebSocket(),o=this.buildUrl(e),r=new t(o),s=!1,i=(a=1000,u="client closed")=>{if(s)return;if(s=!0,r.readyState===C||r.readyState===j)r.close(a,u)};return r.onopen=()=>r.send(JSON.stringify({type:"attach",...e,signal:void 0,agent:void 0})),r.onmessage=(a)=>{if(typeof a.data!=="string")return;let u=q(a.data);if(!u)return;let l=G(u,n);if(n.onMessage?.(l),l.type==="done")n.onDone?.();if(l.type==="error")n.onError?.(Error(J(l.error)))},r.onerror=()=>n.onError?.(L(this.baseUrl)),r.onclose=(a)=>{if(!s&&a.code!==1000)n.onError?.(Error(a.reason||"WebSocket connection closed."))},{url:o,sendControl:function(a){if(r.readyState!==C)throw Error("WebSocket is not open");r.send(JSON.stringify({type:"control",...a}))},close:i}}async*stream(e){let n=[],t=!1,o=null,r=null,s=()=>{r?.(),r=null},i=this.subscribe(e,{onMessage:function(a){n.push(a),s()},onDone:function(){t=!0,s()},onError:function(a){o=a,s()}});try{while(!0){if(n.length>0){yield n.shift();continue}if(o)throw o;if(t)return;await new Promise((a)=>{r=a})}}finally{i.close()}}buildUrl(e){let n=be(e),t=e.projectSlug??e.agent?.projectSlug,o=e.stageSlug??e.agent?.stageSlug,r=t?`/${t}`:"",s=o?`/${o}`:"";return`${ke(this.baseUrl)}/v1${r}/agents${s}/${encodeURIComponent(n)}/ws?token=${encodeURIComponent(this.apiKey)}`}resolveWebSocket(){let e=this.WebSocketImpl??globalThis.WebSocket;if(!e)throw Error("WebSocket is not available. Pass a WebSocket implementation in BroodsWebSocketClient options.");return e}}function Re(e){let n=e.agentId??e.agent?.id??e.endpointId;if(!n)throw Error("WebSocket run requires agent, agentId, or endpointId.");return n}function be(e){let n=e.endpointId??e.agent?.endpointId??e.agent?.id;if(!n)throw Error("WebSocket run requires agent or endpointId.");return n}function ke(e){let n=new URL(F(e));if(n.protocol==="https:")n.protocol="wss:";if(n.protocol==="http:")n.protocol="ws:";return d(n.toString())}function F(e){let n=e.trim();if(/^wss?:\/\//.test(n))return d(n);return A(n)}function L(e){return Error(`Cannot access the WebSocket service at ${e}.`)}function G(e,n){if(e.type!=="output")return e;let t=e;return n.onOutput?.(t),t.data}function q(e){try{let n=JSON.parse(e);return typeof n==="object"&&n!==null&&typeof n.type==="string"?n:null}catch{return null}}function J(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&typeof e.message==="string")return e.message;return e===void 0?"WebSocket stream error.":JSON.stringify(e)}var z=Symbol.for("broods.resource"),V=Symbol.for("broods.config"),Y=Symbol.for("broods.connection"),Z=/^[A-Z][A-Z0-9_]{0,63}$/,ze=new Proxy((e)=>{if(!Z.test(e))throw Error("env name must match /^[A-Z][A-Z0-9_]*$/ and be at most 64 characters.");return{__beeblastEnv:!0,name:e}},{get:function(e,n,t){if(typeof n==="string"&&Z.test(n))throw Error(`env.${n} is not supported; use env("${n}")`);return Reflect.get(e,n,t)}});function g(e,n,t,o){return{[z]:!0,kind:e,name:n,...t?{description:t}:{},config:o}}function f(e,n){let{partition:t,...o}=n;return{[Y]:!0,kind:"connection",type:e,...t?{partition:t}:{},config:o}}function m(e,n,t,o,r){return g("channelRecord",e,n,{...r,externalId:t,...o?{workspaceRef:o}:{}})}function Ve(e){return f("discord",e)}function Ye(e){return f("github",e)}function Xe(e){return f("pancake",e)}function Qe(e){return f("slack",e)}function en(e){return f("telegram",e)}function nn(e){return f("zalo",e)}function tn(e){let{name:n,description:t,channelId:o,guildId:r,...s}=e;return m(n,t,o,r,s)}function on(e){let{name:n,description:t,repo:o,...r}=e,[s,...i]=o.split("/");if(!s||i.length!==1||!i[0])throw Error(`Channel "${n}" repo must be "owner/name", not "${o}"`);return m(n,t,o,s,r)}function rn(e){let{name:n,description:t,conversationId:o,...r}=e;return m(n,t,o,void 0,r)}function sn(e){let{name:n,description:t,channelId:o,teamId:r,...s}=e;return m(n,t,o,r,s)}function an(e){let{name:n,description:t,chatId:o,...r}=e;return m(n,t,o,void 0,r)}function cn(e){let{name:n,description:t,chatId:o,...r}=e;return m(n,t,o,void 0,r)}function un(e){return{[V]:!0,config:e}}function dn(e){let{name:n,description:t,...o}=e;return g("agent",n,t,o)}function ln(e){return e}function gn(e){let{name:n,description:t,...o}=e;return g("workspace",n,t,o)}function pn(e){let{name:n,description:t,...o}=e;return g("sandbox",n,t,o)}function fn(e){let{name:n,description:t,...o}=e;return g("skill",n,t,o)}function mn(e){let{name:n,description:t,...o}=e;return g("mcp",n,t,o)}function yn(e){let{name:n,description:t,...o}=e;return g("policy",n,t,o)}function hn(e){let{name:n,description:t,...o}=e;return g("cron",n,t,o)}function Cn(e){return Boolean(e&&typeof e==="object"&&e[z])}function Sn(e){return Boolean(e&&typeof e==="object"&&e[Y])}function Rn(e){return Boolean(e&&typeof e==="object"&&e[V])}
5
- export{k as a,D as b,Ee as c,De as d,h as e,Ne as f,Oe as g,T as h,d as i,Te as j,I as k,$e as l,x as m,B as n,le as o,A as p,Se as q,ke as r,ze as s,Ve as t,Ye as u,Xe as v,Qe as w,en as x,nn as y,tn as z,on as A,rn as B,sn as C,an as D,cn as E,un as F,dn as G,ln as H,gn as I,pn as J,fn as K,mn as L,yn as M,hn as N,Cn as O,Sn as P,Rn as Q};
@@ -1 +0,0 @@
1
- import{$ as k,W as _,X as q,Y as C,Z as P,_ as j,aa as D,ba as p,ca as v,da as z,ea as A,fa as M,ga as J,ha as L,ia as U,ja as x,ka as O,la as g,ma as F,na as X,oa as H,pa as Q}from"./chunk-zk2w6bee.js";import"./chunk-e66afphr.js";import"./chunk-rx5qcgbh.js";var re=class{_readBuffer;_started=!1;_closed=!1;constructor(r=O.stdin,o=O.stdout,a){this._stdin=r,this._stdout=o,this._readBuffer=new U({maxBufferSize:a?.maxBufferSize})}onclose;onerror;onmessage;_ondata=(r)=>{try{this._readBuffer.append(r),this.processReadBuffer()}catch(o){this.onerror?.(o),this.close().catch(()=>{})}};_onerror=(r)=>{this.onerror?.(r)};_onstdouterror=(r)=>{this.onerror?.(r),this.close().catch(()=>{})};async start(){if(this._started)throw Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror),this._stdout.on("error",this._onstdouterror)}processReadBuffer(){while(!0)try{let r=this._readBuffer.readMessage();if(r===null)break;this.onmessage?.(r)}catch(r){this.onerror?.(r)}}async close(){if(this._closed)return;if(this._closed=!0,this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdout.off("error",this._onstdouterror),this._stdin.listenerCount("data")===0)this._stdin.pause();this._readBuffer.clear(),this.onclose?.()}send(r){if(this._closed)return Promise.reject(Error("StdioServerTransport is closed"));return new Promise((o,a)=>{let d=x(r),t=!1,u=(w)=>{if(t)return;t=!0,this._stdout.off("error",u),this._stdout.off("drain",h),a(w)},h=()=>{if(t)return;t=!0,this._stdout.off("error",u),this._stdout.off("drain",h),o()};if(this._stdout.once("error",u),this._stdout.write(d)){if(t)return;t=!0,this._stdout.off("error",u),o()}else if(!t)this._stdout.once("drain",h)})}},W=3000,te=class{onclose;onerror;onmessage;_closed=!1;_pendingRequests=new Set;_drainWaiters=[];constructor(r,o,a){this._wire=r,this._onInstanceClose=o,this._outboundIntercept=a}async start(){}async send(r,o){if(z(r)||A(r)){let{id:a}=r;if(a!==void 0)this._settle(a)}if(this._closed)return;if(this._outboundIntercept?.(r)==="handled")return;return this._wire.send(r,o)}setProtocolVersion=(r)=>{this._wire.setProtocolVersion?.(r)};deliver(r,o){if(this._closed)return;if(p(r))this._pendingRequests.add(r.id);else if(v(r)&&r.method==="notifications/cancelled"){let a=r.params?.requestId;if(a!==void 0)this._settle(a)}this.onmessage?.(r,o)}async whenRequestsAnswered(r){if(this._closed||this._pendingRequests.size===0)return!0;return await new Promise((o)=>{let a=()=>{clearTimeout(d),o(!0)},d=setTimeout(()=>{this._drainWaiters=this._drainWaiters.filter((t)=>t!==a),o(!1)},r);this._drainWaiters.push(a)})}async close(){if(this._closed)return;this._closed=!0,this._pendingRequests.clear(),this._releaseDrainWaiters();try{this._onInstanceClose()}finally{this.onclose?.()}}_settle(r){if(this._pendingRequests.delete(r),this._pendingRequests.size===0)this._releaseDrainWaiters()}_releaseDrainWaiters(){let r=this._drainWaiters;this._drainWaiters=[];for(let o of r)o()}};function ne(r){let o=r.params;if(r.method==="initialize"&&!M(o)){let u=o!==null&&typeof o==="object"&&typeof o.protocolVersion==="string"?o.protocolVersion:void 0;return{kind:"legacy",reason:"initialize",...u!==void 0&&{requestedVersion:u}}}if(!j(o))return{kind:"legacy",reason:"no-claim"};let a=P(o),d=(a===void 0?[]:D(a))[0];if(d!==void 0)return{kind:"invalid-envelope",issue:d};let t=k(o);if(t===void 0||!_.includes(t))return{kind:"unsupported-revision",requested:t??"unknown"};return{kind:"modern",revision:t,classification:{era:"modern",revision:t}}}function ae(r,o={}){let a=o.legacy??"serve",d=o.transport??new re,t={phase:"opening"},u,h=!1,w=()=>h||t.phase==="closed",c=(e)=>{try{o.onerror?.(e)}catch{}},R=(e,n,i,s)=>d.send({jsonrpc:"2.0",id:e,error:{code:n,message:i,...s!==void 0&&{data:s}}}).catch((l)=>c(f(l))),y=new F(o.maxSubscriptions??g),Y=(e)=>{if(!v(e))return;let n=y.routeOutbound(e);if(n==="passthrough")return;for(let i of n)d.send({jsonrpc:"2.0",...i}).catch((s)=>c(f(s)));return"handled"},V=async(e)=>{if(p(e)&&e.method==="subscriptions/listen"){let n=P(e.params),i=j(e.params)?(n===void 0?[]:D(n))[0]:{key:"_meta",problem:"the per-request envelope is required on protocol revision 2026-07-28"},s=k(e.params),l;if(i!==void 0)l={jsonrpc:"2.0",id:e.id,error:{code:-32602,message:`Invalid _meta envelope: ${i.key}: ${i.problem}`}};else if(s===void 0||!_.includes(s)){let m=new C({supported:[..._],requested:s??"unknown"});l={jsonrpc:"2.0",id:e.id,error:{code:m.code,message:m.message,data:m.data}}}else l=y.serve(e);return await d.send("error"in l?l:{jsonrpc:"2.0",method:l.method,params:l.params}).catch((m)=>c(f(m))),!0}if(v(e)&&e.method==="notifications/cancelled"){let n=e.params?.requestId;if(n!==void 0&&y.cancel(n))return!0}return!1},T=(e,n,i)=>{let s=J({kind:"legacy",reason:n,...i!==void 0&&{requestedVersion:i}},_);if(s===void 0)return Promise.resolve();return c(Error(`Rejected 2025-era request on a modern-only stdio connection (${s.cell}): ${s.message}`)),R(e.id,s.code,s.message,s.data)},G=(e)=>{if(h||e===u)return;B()},S=async(e,n)=>{let i=await r({era:e}),s=i instanceof Q?i.server:i;if(e==="modern")L(s,n),X(s,_),y.setServerCapabilities(s.getCapabilities(),H(s));let l=new te(d,()=>G(l),e==="modern"?Y:void 0);return await i.connect(l),{product:i,channel:l}},E=(e)=>e.product.close().catch((n)=>c(f(n))),K=async(e)=>{u=e.channel;try{if(!await e.channel.whenRequestsAnswered(W))c(Error(`Discarded the probe instance with requests still unanswered after ${W}ms; continuing with the fallback`));await e.product.close()}catch(n){c(f(n))}finally{u=void 0}},Z=async(e)=>{if(t.phase==="closed")return;if(t.phase==="pinned"){if(t.era==="modern"&&p(e)&&e.method==="initialize"&&!M(e.params)){await T(e,"initialize",e.params!==null&&typeof e.params==="object"&&typeof e.params.protocolVersion==="string"?e.params.protocolVersion:void 0);return}if(t.era==="modern"&&await V(e))return;t.instance.channel.deliver(e);return}if(!p(e)&&!v(e)){c(Error("Discarded a JSON-RPC response received before the connection negotiated an era"));return}let n=ne(e);switch(n.kind){case"invalid-envelope":{let i=`Invalid _meta envelope for protocol revision 2026-07-28: ${n.issue.key}: ${n.issue.problem}`;if(p(e))await R(e.id,q.InvalidParams,i,{envelope:n.issue});else c(Error(`Discarded a notification with a malformed envelope: ${i}`));return}case"unsupported-revision":if(p(e)){let i=new C({supported:[..._],requested:n.requested});c(i),await R(e.id,i.code,i.message,i.data)}else c(Error(`Discarded a notification claiming unsupported protocol revision ${n.requested}`));return;case"modern":if(p(e)&&e.method==="server/discover"){if(t.phase==="probe"){t.instance.channel.deliver(e,{classification:n.classification});return}let i=await S("modern",n.revision);if(w()){await E(i);return}t={phase:"probe",instance:i},i.channel.deliver(e,{classification:n.classification});return}if(t.phase==="probe"){if(v(e)){t.instance.channel.deliver(e,{classification:n.classification});return}t={phase:"pinned",era:"modern",instance:t.instance}}else{let i=await S("modern",n.revision);if(w()){await E(i);return}t={phase:"pinned",era:"modern",instance:i}}if(await V(e))return;t.instance.channel.deliver(e,{classification:n.classification});return;case"legacy":{if(a==="reject"){if(p(e))await T(e,n.reason,n.requestedVersion);return}if(t.phase==="probe"){if(await K(t.instance),w())return;t={phase:"opening"}}let i=await S("legacy");if(w()){await E(i);return}t={phase:"pinned",era:"legacy",instance:i},t.instance.channel.deliver(e);return}}},I=[],b=!1,ee=async()=>{if(b)return;b=!0;try{while(I.length>0){let e=I.shift();try{await Z(e)}catch(n){if(p(e))await R(e.id,q.InternalError,"Internal server error");c(f(n))}}}finally{b=!1}},B=async()=>{if(h||t.phase==="closed")return;h=!0;let e=t;t={phase:"closed"};for(let n of y.teardownAll())await d.send(n).catch((i)=>c(f(i)));if(e.phase==="probe"||e.phase==="pinned")await e.instance.product.close().catch((n)=>c(f(n)));await d.close().catch((n)=>c(f(n)))};d.onmessage=(e)=>{I.push(e),ee()},d.onerror=(e)=>{if(c(e),t.phase==="probe"||t.phase==="pinned")t.instance.channel.onerror?.(e)},d.onclose=()=>{if(h||t.phase==="closed")return;h=!0;let e=t;if(t={phase:"closed"},e.phase==="probe"||e.phase==="pinned")e.instance.product.close().catch((n)=>c(f(n)))};let N=d.start().catch((e)=>{throw c(f(e)),e});return N.catch(()=>{}),{close:async()=>{await N.catch(()=>{}),await B()}}}function f(r){return r instanceof Error?r:Error(String(r))}export{re as StdioServerTransport,ae as serveStdio};