broods 0.2.0 → 0.3.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/README.md +74 -0
- package/dist/account.d.ts +799 -0
- package/dist/account.js +271 -0
- package/dist/cli/index.js +54 -1
- package/dist/index.d.ts +363 -4
- package/dist/index.js +269 -1
- package/package.json +6 -1
package/dist/account.js
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/account.ts
|
|
3
|
+
var DEFAULT_ACCOUNT_BASE_URL = "https://gateway.broods.app";
|
|
4
|
+
|
|
5
|
+
class BroodsAccountApiError extends Error {
|
|
6
|
+
status;
|
|
7
|
+
body;
|
|
8
|
+
constructor(method, path, status, body) {
|
|
9
|
+
super(`${method} ${path} failed with ${status}: ${body}`);
|
|
10
|
+
this.name = "BroodsAccountApiError";
|
|
11
|
+
this.status = status;
|
|
12
|
+
this.body = body;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function envVar(name) {
|
|
16
|
+
return typeof process !== "undefined" ? process?.env?.[name] : undefined;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class BroodsAccountClient {
|
|
20
|
+
baseUrl;
|
|
21
|
+
accountSecret;
|
|
22
|
+
fetchImpl;
|
|
23
|
+
constructor(options = {}) {
|
|
24
|
+
const baseUrl = options.baseUrl ?? envVar("BROODS_BASE_URL") ?? DEFAULT_ACCOUNT_BASE_URL;
|
|
25
|
+
const accountSecret = options.accountSecret ?? envVar("BROODS_ACCOUNT_SECRET");
|
|
26
|
+
if (!accountSecret)
|
|
27
|
+
throw new Error("BroodsAccountClient requires an accountSecret (or BROODS_ACCOUNT_SECRET).");
|
|
28
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
29
|
+
this.accountSecret = accountSecret;
|
|
30
|
+
this.fetchImpl = options.fetch ?? fetch;
|
|
31
|
+
}
|
|
32
|
+
async getAccount() {
|
|
33
|
+
const result = await this.request("GET", "/v1/account");
|
|
34
|
+
if (!result)
|
|
35
|
+
throw new BroodsAccountApiError("GET", "/v1/account", 404, "Account not found");
|
|
36
|
+
return result.account;
|
|
37
|
+
}
|
|
38
|
+
async updateAccount(patch) {
|
|
39
|
+
const result = await this.request("PATCH", "/v1/account", patch);
|
|
40
|
+
return result?.account ?? null;
|
|
41
|
+
}
|
|
42
|
+
async rotateSecret() {
|
|
43
|
+
const result = await this.request("POST", "/v1/account/rotate-secret");
|
|
44
|
+
if (!result)
|
|
45
|
+
throw new BroodsAccountApiError("POST", "/v1/account/rotate-secret", 404, "Account not found");
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
async deleteAccount() {
|
|
49
|
+
const result = await this.request("DELETE", "/v1/account");
|
|
50
|
+
return result ?? { deleted: false };
|
|
51
|
+
}
|
|
52
|
+
webhookUrl(accountId, agentId, channelType) {
|
|
53
|
+
const segments = [accountId, agentId, channelType].map(encodeURIComponent);
|
|
54
|
+
return `${this.baseUrl}/webhooks/${segments.join("/")}`;
|
|
55
|
+
}
|
|
56
|
+
async listAgents() {
|
|
57
|
+
const result = await this.request("GET", "/v1/agents");
|
|
58
|
+
return result?.agents ?? [];
|
|
59
|
+
}
|
|
60
|
+
async createAgent(input) {
|
|
61
|
+
const result = await this.request("POST", "/v1/agents", input);
|
|
62
|
+
if (!result)
|
|
63
|
+
throw new BroodsAccountApiError("POST", "/v1/agents", 404, "Not found");
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
async getAgent(agentId) {
|
|
67
|
+
return await this.request("GET", `/v1/agents/${encodeURIComponent(agentId)}`);
|
|
68
|
+
}
|
|
69
|
+
async updateAgent(agentId, patch) {
|
|
70
|
+
return await this.request("PATCH", `/v1/agents/${encodeURIComponent(agentId)}`, patch);
|
|
71
|
+
}
|
|
72
|
+
async deleteAgent(agentId) {
|
|
73
|
+
const result = await this.request("DELETE", `/v1/agents/${encodeURIComponent(agentId)}`);
|
|
74
|
+
return result?.deleted ?? false;
|
|
75
|
+
}
|
|
76
|
+
async listCrons() {
|
|
77
|
+
const result = await this.request("GET", "/v1/crons");
|
|
78
|
+
return result?.crons ?? [];
|
|
79
|
+
}
|
|
80
|
+
async createCron(input) {
|
|
81
|
+
const result = await this.request("POST", "/v1/crons", input);
|
|
82
|
+
if (!result)
|
|
83
|
+
throw new BroodsAccountApiError("POST", "/v1/crons", 404, "Not found");
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
async getCron(cronId) {
|
|
87
|
+
return await this.request("GET", `/v1/crons/${encodeURIComponent(cronId)}`);
|
|
88
|
+
}
|
|
89
|
+
async updateCron(cronId, patch) {
|
|
90
|
+
return await this.request("PATCH", `/v1/crons/${encodeURIComponent(cronId)}`, patch);
|
|
91
|
+
}
|
|
92
|
+
async deleteCron(cronId) {
|
|
93
|
+
const result = await this.request("DELETE", `/v1/crons/${encodeURIComponent(cronId)}`);
|
|
94
|
+
return result?.deleted ?? false;
|
|
95
|
+
}
|
|
96
|
+
async listCronRuns(cronId, options = {}) {
|
|
97
|
+
const query = options.limit !== undefined ? `?limit=${options.limit}` : "";
|
|
98
|
+
const result = await this.request("GET", `/v1/crons/${encodeURIComponent(cronId)}/runs${query}`);
|
|
99
|
+
return result?.runs ?? [];
|
|
100
|
+
}
|
|
101
|
+
async listWorkspaces() {
|
|
102
|
+
const result = await this.request("GET", "/v1/workspaces");
|
|
103
|
+
return result?.workspaces ?? [];
|
|
104
|
+
}
|
|
105
|
+
async createWorkspace(input) {
|
|
106
|
+
const result = await this.request("POST", "/v1/workspaces", input);
|
|
107
|
+
if (!result)
|
|
108
|
+
throw new BroodsAccountApiError("POST", "/v1/workspaces", 404, "Not found");
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
async getWorkspace(workspaceId) {
|
|
112
|
+
return await this.request("GET", `/v1/workspaces/${encodeURIComponent(workspaceId)}`);
|
|
113
|
+
}
|
|
114
|
+
async updateWorkspace(workspaceId, patch) {
|
|
115
|
+
return await this.request("PATCH", `/v1/workspaces/${encodeURIComponent(workspaceId)}`, patch);
|
|
116
|
+
}
|
|
117
|
+
async deleteWorkspace(workspaceId) {
|
|
118
|
+
const result = await this.request("DELETE", `/v1/workspaces/${encodeURIComponent(workspaceId)}`);
|
|
119
|
+
return result?.deleted ?? false;
|
|
120
|
+
}
|
|
121
|
+
async listWorkspaceFiles(workspaceId) {
|
|
122
|
+
const result = await this.request("GET", `/v1/workspaces/${encodeURIComponent(workspaceId)}/files`);
|
|
123
|
+
return result?.files ?? [];
|
|
124
|
+
}
|
|
125
|
+
async getWorkspaceFileUrl(workspaceId, path) {
|
|
126
|
+
const query = `?path=${encodeURIComponent(path)}`;
|
|
127
|
+
const result = await this.request("GET", `/v1/workspaces/${encodeURIComponent(workspaceId)}/files${query}`);
|
|
128
|
+
return result?.url ?? null;
|
|
129
|
+
}
|
|
130
|
+
async uploadWorkspaceFile(workspaceId, input) {
|
|
131
|
+
const path = `/v1/workspaces/${encodeURIComponent(workspaceId)}/files`;
|
|
132
|
+
const result = await this.request("POST", path, input);
|
|
133
|
+
if (!result)
|
|
134
|
+
throw new BroodsAccountApiError("POST", path, 404, "Workspace not found");
|
|
135
|
+
return result.file;
|
|
136
|
+
}
|
|
137
|
+
async renameWorkspaceFile(workspaceId, path, newPath) {
|
|
138
|
+
const result = await this.request("PATCH", `/v1/workspaces/${encodeURIComponent(workspaceId)}/files`, { path, newPath });
|
|
139
|
+
return result?.renamed ?? false;
|
|
140
|
+
}
|
|
141
|
+
async deleteWorkspaceFile(workspaceId, path) {
|
|
142
|
+
const result = await this.request("DELETE", `/v1/workspaces/${encodeURIComponent(workspaceId)}/files`, { path });
|
|
143
|
+
return result?.deleted ?? false;
|
|
144
|
+
}
|
|
145
|
+
async listSandboxes() {
|
|
146
|
+
const result = await this.request("GET", "/v1/sandboxes");
|
|
147
|
+
return result?.sandboxes ?? [];
|
|
148
|
+
}
|
|
149
|
+
async createSandbox(input) {
|
|
150
|
+
const result = await this.request("POST", "/v1/sandboxes", input);
|
|
151
|
+
if (!result)
|
|
152
|
+
throw new BroodsAccountApiError("POST", "/v1/sandboxes", 404, "Not found");
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
async getSandbox(sandboxId) {
|
|
156
|
+
return await this.request("GET", `/v1/sandboxes/${encodeURIComponent(sandboxId)}`);
|
|
157
|
+
}
|
|
158
|
+
async updateSandbox(sandboxId, patch) {
|
|
159
|
+
return await this.request("PATCH", `/v1/sandboxes/${encodeURIComponent(sandboxId)}`, patch);
|
|
160
|
+
}
|
|
161
|
+
async deleteSandbox(sandboxId) {
|
|
162
|
+
const result = await this.request("DELETE", `/v1/sandboxes/${encodeURIComponent(sandboxId)}`);
|
|
163
|
+
return result?.deleted ?? false;
|
|
164
|
+
}
|
|
165
|
+
async suspendSandbox(sandboxId, reservationKey) {
|
|
166
|
+
return await this.sandboxAction(sandboxId, "suspend", { reservationKey });
|
|
167
|
+
}
|
|
168
|
+
async resumeSandbox(sandboxId, reservationKey) {
|
|
169
|
+
return await this.sandboxAction(sandboxId, "resume", { reservationKey });
|
|
170
|
+
}
|
|
171
|
+
async terminateSandbox(sandboxId, reservationKey) {
|
|
172
|
+
return await this.sandboxAction(sandboxId, "terminate", { reservationKey });
|
|
173
|
+
}
|
|
174
|
+
async snapshotSandbox(sandboxId, reservationKey, name) {
|
|
175
|
+
return await this.sandboxAction(sandboxId, "snapshot", { reservationKey, name });
|
|
176
|
+
}
|
|
177
|
+
async openSandboxTerminal(sandboxId, reservationKey) {
|
|
178
|
+
return await this.sandboxAction(sandboxId, "terminal", { reservationKey });
|
|
179
|
+
}
|
|
180
|
+
async listTools() {
|
|
181
|
+
const result = await this.request("GET", "/v1/tools");
|
|
182
|
+
return result?.tools ?? [];
|
|
183
|
+
}
|
|
184
|
+
async createTool(input) {
|
|
185
|
+
const result = await this.request("POST", "/v1/tools", input);
|
|
186
|
+
if (!result)
|
|
187
|
+
throw new BroodsAccountApiError("POST", "/v1/tools", 404, "Not found");
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
async getTool(toolId) {
|
|
191
|
+
return await this.request("GET", `/v1/tools/${encodeURIComponent(toolId)}`);
|
|
192
|
+
}
|
|
193
|
+
async updateTool(toolId, patch) {
|
|
194
|
+
return await this.request("PATCH", `/v1/tools/${encodeURIComponent(toolId)}`, patch);
|
|
195
|
+
}
|
|
196
|
+
async deleteTool(toolId) {
|
|
197
|
+
const result = await this.request("DELETE", `/v1/tools/${encodeURIComponent(toolId)}`);
|
|
198
|
+
return result?.deleted ?? false;
|
|
199
|
+
}
|
|
200
|
+
async listPolicies() {
|
|
201
|
+
const result = await this.request("GET", "/v1/policies");
|
|
202
|
+
return result?.policies ?? [];
|
|
203
|
+
}
|
|
204
|
+
async createPolicy(input) {
|
|
205
|
+
const result = await this.request("POST", "/v1/policies", input);
|
|
206
|
+
if (!result)
|
|
207
|
+
throw new BroodsAccountApiError("POST", "/v1/policies", 404, "Not found");
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
async getPolicy(policyId) {
|
|
211
|
+
return await this.request("GET", `/v1/policies/${encodeURIComponent(policyId)}`);
|
|
212
|
+
}
|
|
213
|
+
async updatePolicy(policyId, patch) {
|
|
214
|
+
return await this.request("PATCH", `/v1/policies/${encodeURIComponent(policyId)}`, patch);
|
|
215
|
+
}
|
|
216
|
+
async deletePolicy(policyId) {
|
|
217
|
+
const result = await this.request("DELETE", `/v1/policies/${encodeURIComponent(policyId)}`);
|
|
218
|
+
return result?.deleted ?? false;
|
|
219
|
+
}
|
|
220
|
+
async listSkills() {
|
|
221
|
+
const result = await this.request("GET", "/v1/skills");
|
|
222
|
+
return result?.skills ?? [];
|
|
223
|
+
}
|
|
224
|
+
async createSkill(input) {
|
|
225
|
+
const result = await this.request("POST", "/v1/skills", input);
|
|
226
|
+
if (!result)
|
|
227
|
+
throw new BroodsAccountApiError("POST", "/v1/skills", 404, "Not found");
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
230
|
+
async getSkill(skillName) {
|
|
231
|
+
return await this.request("GET", `/v1/skills/${encodeURIComponent(skillName)}`);
|
|
232
|
+
}
|
|
233
|
+
async uploadSkill(skillName, input) {
|
|
234
|
+
const path = `/v1/skills/${encodeURIComponent(skillName)}`;
|
|
235
|
+
const result = await this.request("PUT", path, input);
|
|
236
|
+
if (!result)
|
|
237
|
+
throw new BroodsAccountApiError("PUT", path, 404, "Skill not found");
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
async deleteSkill(skillName) {
|
|
241
|
+
const result = await this.request("DELETE", `/v1/skills/${encodeURIComponent(skillName)}`);
|
|
242
|
+
return result?.deleted ?? false;
|
|
243
|
+
}
|
|
244
|
+
async sandboxAction(sandboxId, action, body) {
|
|
245
|
+
const path = `/v1/sandboxes/${encodeURIComponent(sandboxId)}/${action}`;
|
|
246
|
+
const result = await this.request("POST", path, body);
|
|
247
|
+
if (!result)
|
|
248
|
+
throw new BroodsAccountApiError("POST", path, 404, "Sandbox not found");
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
async request(method, path, body) {
|
|
252
|
+
const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
253
|
+
method,
|
|
254
|
+
headers: {
|
|
255
|
+
Authorization: `Bearer ${this.accountSecret}`,
|
|
256
|
+
...body !== undefined ? { "Content-Type": "application/json" } : {}
|
|
257
|
+
},
|
|
258
|
+
...body !== undefined ? { body: JSON.stringify(body) } : {}
|
|
259
|
+
});
|
|
260
|
+
if (response.status === 404)
|
|
261
|
+
return null;
|
|
262
|
+
if (!response.ok) {
|
|
263
|
+
throw new BroodsAccountApiError(method, path, response.status, await response.text());
|
|
264
|
+
}
|
|
265
|
+
return await response.json();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
export {
|
|
269
|
+
BroodsAccountClient,
|
|
270
|
+
BroodsAccountApiError
|
|
271
|
+
};
|
package/dist/cli/index.js
CHANGED
|
@@ -686,8 +686,56 @@ async function normalizeConfig(resource, projectRoot) {
|
|
|
686
686
|
}
|
|
687
687
|
return rewriteValues(resource.config);
|
|
688
688
|
}
|
|
689
|
+
var KNOWN_PROVIDER_NAMES = ["google", "openai", "anthropic", "bedrock", "gateway", "minimax", "custom"];
|
|
690
|
+
var KNOWN_PROVIDER_SETTING_KEYS = new Set([
|
|
691
|
+
"apiKey",
|
|
692
|
+
"base_url",
|
|
693
|
+
"baseURL",
|
|
694
|
+
"headers",
|
|
695
|
+
"organization",
|
|
696
|
+
"project",
|
|
697
|
+
"name",
|
|
698
|
+
"region",
|
|
699
|
+
"accessKeyId",
|
|
700
|
+
"secretAccessKey",
|
|
701
|
+
"sessionToken"
|
|
702
|
+
]);
|
|
703
|
+
function suggestProviderKey(key) {
|
|
704
|
+
const canonical = key.replace(/[^a-z0-9]/gi, "").toLowerCase();
|
|
705
|
+
if (canonical === "baseurl")
|
|
706
|
+
return `"base_url" or "baseURL"`;
|
|
707
|
+
if (canonical === "apikey")
|
|
708
|
+
return `"apiKey"`;
|
|
709
|
+
return "";
|
|
710
|
+
}
|
|
711
|
+
function validateProviderConfig(agentName, provider) {
|
|
712
|
+
if (provider === undefined || provider === null)
|
|
713
|
+
return;
|
|
714
|
+
if (typeof provider !== "object" || Array.isArray(provider)) {
|
|
715
|
+
throw new Error(`Agent "${agentName}" config.provider must be an object`);
|
|
716
|
+
}
|
|
717
|
+
for (const [providerName, settings] of Object.entries(provider)) {
|
|
718
|
+
if (!KNOWN_PROVIDER_NAMES.includes(providerName)) {
|
|
719
|
+
throw new Error(`Agent "${agentName}" config.provider.${providerName} is not a supported provider (expected one of: ${KNOWN_PROVIDER_NAMES.join(", ")})`);
|
|
720
|
+
}
|
|
721
|
+
if (typeof settings !== "object" || settings === null || Array.isArray(settings)) {
|
|
722
|
+
throw new Error(`Agent "${agentName}" config.provider.${providerName} must be an object`);
|
|
723
|
+
}
|
|
724
|
+
const record = settings;
|
|
725
|
+
for (const key of Object.keys(record)) {
|
|
726
|
+
if (KNOWN_PROVIDER_SETTING_KEYS.has(key))
|
|
727
|
+
continue;
|
|
728
|
+
const suggestion = suggestProviderKey(key);
|
|
729
|
+
throw new Error(`Agent "${agentName}" config.provider.${providerName} has unknown option "${key}"${suggestion ? ` \u2014 did you mean ${suggestion}?` : ""}`);
|
|
730
|
+
}
|
|
731
|
+
if (providerName === "custom" && record.base_url === undefined && record.baseURL === undefined) {
|
|
732
|
+
throw new Error(`Agent "${agentName}" config.provider.custom.base_url is required (use "base_url" or "baseURL")`);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
689
736
|
function normalizeAgentConfig(resource, _projectRoot) {
|
|
690
737
|
const config = { ...resource.config };
|
|
738
|
+
validateProviderConfig(resource.name, config.provider);
|
|
691
739
|
const inlineHooks = normalizeInlineAgentHooks(resource.name, config.hooks);
|
|
692
740
|
if (inlineHooks) {
|
|
693
741
|
config.hooks = inlineHooks.agentHooksConfig;
|
|
@@ -2547,7 +2595,7 @@ function renderStreamPart(part, state) {
|
|
|
2547
2595
|
// package.json
|
|
2548
2596
|
var package_default = {
|
|
2549
2597
|
name: "broods",
|
|
2550
|
-
version: "0.
|
|
2598
|
+
version: "0.3.0",
|
|
2551
2599
|
description: "CLI + TypeScript SDK for the broods agent platform.",
|
|
2552
2600
|
type: "module",
|
|
2553
2601
|
license: "MIT",
|
|
@@ -2574,6 +2622,10 @@ var package_default = {
|
|
|
2574
2622
|
".": {
|
|
2575
2623
|
types: "./dist/index.d.ts",
|
|
2576
2624
|
import: "./dist/index.js"
|
|
2625
|
+
},
|
|
2626
|
+
"./account": {
|
|
2627
|
+
types: "./dist/account.d.ts",
|
|
2628
|
+
import: "./dist/account.js"
|
|
2577
2629
|
}
|
|
2578
2630
|
},
|
|
2579
2631
|
main: "./dist/index.js",
|
|
@@ -2602,6 +2654,7 @@ var package_default = {
|
|
|
2602
2654
|
devDependencies: {
|
|
2603
2655
|
"@types/bun": "^1.3.14",
|
|
2604
2656
|
rollup: "^4.53.3",
|
|
2657
|
+
typescript: "^6.0.3",
|
|
2605
2658
|
"rollup-plugin-dts": "^6.3.0"
|
|
2606
2659
|
}
|
|
2607
2660
|
};
|