@agent-foundry/studio 1.0.0 → 1.0.2

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.
Files changed (44) hide show
  1. package/README.md +180 -47
  2. package/dist/bff/client.d.ts +168 -0
  3. package/dist/bff/client.d.ts.map +1 -0
  4. package/dist/bff/client.js +288 -0
  5. package/dist/bff/client.js.map +1 -0
  6. package/dist/bff/index.d.ts +27 -0
  7. package/dist/bff/index.d.ts.map +1 -0
  8. package/dist/bff/index.js +26 -0
  9. package/dist/bff/index.js.map +1 -0
  10. package/dist/bff/types.d.ts +168 -0
  11. package/dist/bff/types.d.ts.map +1 -0
  12. package/dist/bff/types.js +8 -0
  13. package/dist/bff/types.js.map +1 -0
  14. package/dist/db/deployments.d.ts +67 -1
  15. package/dist/db/deployments.d.ts.map +1 -1
  16. package/dist/db/deployments.js +92 -1
  17. package/dist/db/deployments.js.map +1 -1
  18. package/dist/db/index.d.ts +17 -0
  19. package/dist/db/index.d.ts.map +1 -1
  20. package/dist/db/index.js +17 -0
  21. package/dist/db/index.js.map +1 -1
  22. package/dist/db/projects.d.ts +54 -1
  23. package/dist/db/projects.d.ts.map +1 -1
  24. package/dist/db/projects.js +79 -1
  25. package/dist/db/projects.js.map +1 -1
  26. package/dist/index.d.ts +14 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +16 -2
  29. package/dist/index.js.map +1 -1
  30. package/dist/types/deployment.d.ts +56 -0
  31. package/dist/types/deployment.d.ts.map +1 -1
  32. package/dist/types/project.d.ts +6 -0
  33. package/dist/types/project.d.ts.map +1 -1
  34. package/package.json +14 -4
  35. package/src/bff/client.ts +412 -0
  36. package/src/bff/index.ts +32 -0
  37. package/src/bff/types.ts +212 -0
  38. package/src/db/deployments.ts +99 -1
  39. package/src/db/index.ts +17 -0
  40. package/src/db/projects.ts +86 -1
  41. package/src/db/schema.sql +35 -52
  42. package/src/index.ts +18 -2
  43. package/src/types/deployment.ts +75 -0
  44. package/src/types/project.ts +7 -0
@@ -1 +1 @@
1
- {"version":3,"file":"deployment.d.ts","sourceRoot":"","sources":["../../src/types/deployment.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deployment.d.ts","sourceRoot":"","sources":["../../src/types/deployment.ts"],"names":[],"mappings":"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"}
@@ -37,6 +37,12 @@ export interface StudioProject {
37
37
  slug: string;
38
38
  /** Optional project description */
39
39
  description?: string;
40
+ /**
41
+ * Registered app ID after publishing to Feed.
42
+ * Format: com.agentfoundry.studio.{user_prefix}.{slug}
43
+ * Set after first successful publish.
44
+ */
45
+ appId?: string;
40
46
  /** Local filesystem path to project root */
41
47
  rootPath: string;
42
48
  /** Frontend framework used */
@@ -1 +1 @@
1
- {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/types/project.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,aAAa,CAAC;AAE5F;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,mCAAmC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IAEX,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IAEf,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IAEb,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IAEb,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IAEjB,8BAA8B;IAC9B,SAAS,EAAE,gBAAgB,CAAC;IAE5B,4BAA4B;IAC5B,MAAM,EAAE,aAAa,CAAC;IAEtB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAElB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAE7B,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,qBAAqB;IACrB,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;IAE7C,sBAAsB;IACtB,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAC3B"}
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../src/types/project.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,aAAa,CAAC;AAE5F;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,mCAAmC;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IAEX,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IAEf,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IAEb,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IAEb,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IAEjB,8BAA8B;IAC9B,SAAS,EAAE,gBAAgB,CAAC;IAE5B,4BAA4B;IAC5B,MAAM,EAAE,aAAa,CAAC;IAEtB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAElB,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAE7B,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,qBAAqB;IACrB,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,MAAM,CAAC;IAE7C,sBAAsB;IACtB,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAC3B"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agent-foundry/studio",
3
- "version": "1.0.0",
4
- "description": "Full SDK for Agent Foundry Build Studio - types, OSS upload, and Supabase client",
3
+ "version": "1.0.2",
4
+ "description": "Full SDK for Agent Foundry Build Studio - types, BFF API client, OSS upload, and Supabase client",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.js",
@@ -19,6 +19,10 @@
19
19
  "import": "./dist/oss/index.js",
20
20
  "types": "./dist/oss/index.d.ts"
21
21
  },
22
+ "./bff": {
23
+ "import": "./dist/bff/index.js",
24
+ "types": "./dist/bff/index.d.ts"
25
+ },
22
26
  "./db": {
23
27
  "import": "./dist/db/index.js",
24
28
  "types": "./dist/db/index.d.ts"
@@ -28,6 +32,9 @@
28
32
  "build": "tsc",
29
33
  "dev": "tsc --watch",
30
34
  "clean": "rimraf dist",
35
+ "test": "vitest run",
36
+ "test:watch": "vitest",
37
+ "test:integration": "vitest run --config vitest.integration.config.ts",
31
38
  "prepublishOnly": "pnpm run clean && pnpm run build"
32
39
  },
33
40
  "keywords": [
@@ -48,8 +55,11 @@
48
55
  "devDependencies": {
49
56
  "@types/ali-oss": "^6.16.0",
50
57
  "@types/node": "^20.10.0",
58
+ "dotenv": "^16.3.1",
59
+ "jose": "^5.2.0",
60
+ "rimraf": "^5.0.5",
51
61
  "typescript": "^5.3.3",
52
- "rimraf": "^5.0.5"
62
+ "vitest": "^2.0.0"
53
63
  },
54
64
  "files": [
55
65
  "dist",
@@ -59,4 +69,4 @@
59
69
  "publishConfig": {
60
70
  "access": "public"
61
71
  }
62
- }
72
+ }
@@ -0,0 +1,412 @@
1
+ /**
2
+ * BFF API Client
3
+ *
4
+ * Client for interacting with the BFF Studio API endpoints.
5
+ * All write operations (create, update, delete) should go through this client.
6
+ *
7
+ * The BFF uses SQLAlchemy with service_role credentials, which bypasses RLS.
8
+ * This is the secure and recommended way to perform write operations.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { createBFFClient } from '@agent-foundry/studio/bff';
13
+ *
14
+ * const client = createBFFClient({
15
+ * baseUrl: 'http://localhost:11001',
16
+ * authToken: 'your-supabase-jwt',
17
+ * });
18
+ *
19
+ * // Create a project
20
+ * const project = await client.projects.create({
21
+ * name: 'My App',
22
+ * slug: 'my-app',
23
+ * rootPath: '/Users/me/projects/my-app',
24
+ * });
25
+ * ```
26
+ */
27
+
28
+ import type { StudioProject, CreateProjectInput, UpdateProjectInput } from '../types/project';
29
+ import type { Deployment, DeploymentMetadata } from '../types/deployment';
30
+ import type {
31
+ BFFClientConfig,
32
+ CreateProjectRequest,
33
+ UpdateProjectRequest,
34
+ ForkProjectRequest,
35
+ ProjectResponse,
36
+ ProjectListResponse,
37
+ StartDeploymentRequest,
38
+ StartDeploymentResponse,
39
+ UpdateDeploymentStatusRequest,
40
+ CompleteDeploymentRequest,
41
+ CompleteDeploymentResponse,
42
+ FailDeploymentRequest,
43
+ DeploymentListResponse,
44
+ PublishRequest,
45
+ PublishResponse,
46
+ APIError,
47
+ } from './types';
48
+
49
+ /**
50
+ * Error thrown by BFF API client
51
+ */
52
+ export class BFFAPIError extends Error {
53
+ constructor(
54
+ message: string,
55
+ public readonly status: number,
56
+ public readonly detail?: string,
57
+ public readonly code?: string
58
+ ) {
59
+ super(message);
60
+ this.name = 'BFFAPIError';
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Projects API client
66
+ */
67
+ export class ProjectsAPI {
68
+ constructor(
69
+ private readonly baseUrl: string,
70
+ private readonly authToken: string,
71
+ private readonly timeout: number
72
+ ) {}
73
+
74
+ private get headers(): HeadersInit {
75
+ return {
76
+ 'Content-Type': 'application/json',
77
+ 'Authorization': `Bearer ${this.authToken}`,
78
+ };
79
+ }
80
+
81
+ private async request<T>(
82
+ method: string,
83
+ path: string,
84
+ body?: unknown
85
+ ): Promise<T> {
86
+ const controller = new AbortController();
87
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
88
+
89
+ try {
90
+ const response = await fetch(`${this.baseUrl}${path}`, {
91
+ method,
92
+ headers: this.headers,
93
+ body: body ? JSON.stringify(body) : undefined,
94
+ signal: controller.signal,
95
+ });
96
+
97
+ clearTimeout(timeoutId);
98
+
99
+ if (!response.ok) {
100
+ let detail: string | undefined;
101
+ let code: string | undefined;
102
+ try {
103
+ const error: APIError = await response.json();
104
+ detail = error.detail;
105
+ code = error.code;
106
+ } catch {
107
+ detail = await response.text();
108
+ }
109
+ throw new BFFAPIError(
110
+ `BFF API error: ${response.status}`,
111
+ response.status,
112
+ detail,
113
+ code
114
+ );
115
+ }
116
+
117
+ // Handle 204 No Content
118
+ if (response.status === 204) {
119
+ return undefined as T;
120
+ }
121
+
122
+ return response.json();
123
+ } finally {
124
+ clearTimeout(timeoutId);
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Create a new project
130
+ */
131
+ async create(input: CreateProjectInput): Promise<StudioProject> {
132
+ const request: CreateProjectRequest = {
133
+ name: input.name,
134
+ slug: input.slug,
135
+ description: input.description,
136
+ rootPath: input.rootPath,
137
+ framework: input.framework,
138
+ config: input.config,
139
+ parentProjectId: input.parentProjectId,
140
+ };
141
+
142
+ return this.request<ProjectResponse>('POST', '/studio/projects', request);
143
+ }
144
+
145
+ /**
146
+ * Get a project by ID
147
+ */
148
+ async get(id: string): Promise<ProjectResponse> {
149
+ return this.request<ProjectResponse>('GET', `/studio/projects/${id}`);
150
+ }
151
+
152
+ /**
153
+ * List all projects with optional pagination
154
+ */
155
+ async list(options?: {
156
+ page?: number;
157
+ pageSize?: number;
158
+ framework?: string;
159
+ search?: string;
160
+ }): Promise<ProjectListResponse> {
161
+ const params = new URLSearchParams();
162
+ if (options?.page) params.set('page', String(options.page));
163
+ if (options?.pageSize) params.set('pageSize', String(options.pageSize));
164
+ if (options?.framework) params.set('framework', options.framework);
165
+ if (options?.search) params.set('search', options.search);
166
+
167
+ const query = params.toString();
168
+ const path = query ? `/studio/projects?${query}` : '/studio/projects';
169
+ return this.request<ProjectListResponse>('GET', path);
170
+ }
171
+
172
+ /**
173
+ * Update a project
174
+ */
175
+ async update(id: string, input: UpdateProjectInput): Promise<StudioProject> {
176
+ const request: UpdateProjectRequest = {
177
+ name: input.name,
178
+ description: input.description,
179
+ config: input.config,
180
+ };
181
+
182
+ return this.request<ProjectResponse>('PUT', `/studio/projects/${id}`, request);
183
+ }
184
+
185
+ /**
186
+ * Delete a project
187
+ */
188
+ async delete(id: string): Promise<void> {
189
+ return this.request<void>('DELETE', `/studio/projects/${id}`);
190
+ }
191
+
192
+ /**
193
+ * Fork a project
194
+ */
195
+ async fork(
196
+ id: string,
197
+ options: { newSlug: string; newRootPath: string; newName?: string }
198
+ ): Promise<StudioProject> {
199
+ const request: ForkProjectRequest = {
200
+ newSlug: options.newSlug,
201
+ newRootPath: options.newRootPath,
202
+ newName: options.newName,
203
+ };
204
+
205
+ return this.request<ProjectResponse>('POST', `/studio/projects/${id}/fork`, request);
206
+ }
207
+
208
+ /**
209
+ * Publish a project to Feed
210
+ */
211
+ async publish(
212
+ id: string,
213
+ options?: PublishRequest
214
+ ): Promise<PublishResponse> {
215
+ return this.request<PublishResponse>(
216
+ 'POST',
217
+ `/studio/projects/${id}/publish`,
218
+ options ?? {}
219
+ );
220
+ }
221
+ }
222
+
223
+ /**
224
+ * Deployments API client
225
+ */
226
+ export class DeploymentsAPI {
227
+ constructor(
228
+ private readonly baseUrl: string,
229
+ private readonly authToken: string,
230
+ private readonly timeout: number
231
+ ) {}
232
+
233
+ private get headers(): HeadersInit {
234
+ return {
235
+ 'Content-Type': 'application/json',
236
+ 'Authorization': `Bearer ${this.authToken}`,
237
+ };
238
+ }
239
+
240
+ private async request<T>(
241
+ method: string,
242
+ path: string,
243
+ body?: unknown
244
+ ): Promise<T> {
245
+ const controller = new AbortController();
246
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
247
+
248
+ try {
249
+ const response = await fetch(`${this.baseUrl}${path}`, {
250
+ method,
251
+ headers: this.headers,
252
+ body: body ? JSON.stringify(body) : undefined,
253
+ signal: controller.signal,
254
+ });
255
+
256
+ clearTimeout(timeoutId);
257
+
258
+ if (!response.ok) {
259
+ let detail: string | undefined;
260
+ let code: string | undefined;
261
+ try {
262
+ const error: APIError = await response.json();
263
+ detail = error.detail;
264
+ code = error.code;
265
+ } catch {
266
+ detail = await response.text();
267
+ }
268
+ throw new BFFAPIError(
269
+ `BFF API error: ${response.status}`,
270
+ response.status,
271
+ detail,
272
+ code
273
+ );
274
+ }
275
+
276
+ return response.json();
277
+ } finally {
278
+ clearTimeout(timeoutId);
279
+ }
280
+ }
281
+
282
+ /**
283
+ * Start a new deployment (creates deployment record and returns STS credentials)
284
+ */
285
+ async start(input: {
286
+ projectId: string;
287
+ version?: string;
288
+ metadata?: Partial<DeploymentMetadata>;
289
+ }): Promise<StartDeploymentResponse> {
290
+ const request: StartDeploymentRequest = {
291
+ projectId: input.projectId,
292
+ version: input.version,
293
+ metadata: input.metadata,
294
+ };
295
+
296
+ return this.request<StartDeploymentResponse>(
297
+ 'POST',
298
+ '/studio/deployments/start',
299
+ request
300
+ );
301
+ }
302
+
303
+ /**
304
+ * Get a deployment by ID
305
+ */
306
+ async get(id: string): Promise<Deployment> {
307
+ return this.request<Deployment>('GET', `/studio/deployments/${id}`);
308
+ }
309
+
310
+ /**
311
+ * List deployments for a project
312
+ */
313
+ async list(projectId: string, limit?: number): Promise<DeploymentListResponse> {
314
+ const params = new URLSearchParams();
315
+ if (limit) params.set('limit', String(limit));
316
+
317
+ const query = params.toString();
318
+ const path = query
319
+ ? `/studio/projects/${projectId}/deployments?${query}`
320
+ : `/studio/projects/${projectId}/deployments`;
321
+
322
+ return this.request<DeploymentListResponse>('GET', path);
323
+ }
324
+
325
+ /**
326
+ * Update deployment status
327
+ */
328
+ async updateStatus(
329
+ id: string,
330
+ input: UpdateDeploymentStatusRequest
331
+ ): Promise<{ status: string; deploymentId: string }> {
332
+ return this.request<{ status: string; deploymentId: string }>(
333
+ 'PUT',
334
+ `/studio/deployments/${id}/status`,
335
+ input
336
+ );
337
+ }
338
+
339
+ /**
340
+ * Mark deployment as complete (after successful OSS upload)
341
+ */
342
+ async complete(
343
+ id: string,
344
+ input: CompleteDeploymentRequest
345
+ ): Promise<CompleteDeploymentResponse> {
346
+ return this.request<CompleteDeploymentResponse>(
347
+ 'POST',
348
+ `/studio/deployments/${id}/complete`,
349
+ input
350
+ );
351
+ }
352
+
353
+ /**
354
+ * Mark deployment as failed
355
+ */
356
+ async fail(
357
+ id: string,
358
+ input: FailDeploymentRequest
359
+ ): Promise<{ status: string; deploymentId: string }> {
360
+ return this.request<{ status: string; deploymentId: string }>(
361
+ 'POST',
362
+ `/studio/deployments/${id}/fail`,
363
+ input
364
+ );
365
+ }
366
+ }
367
+
368
+ /**
369
+ * BFF Client - main entry point for BFF API operations
370
+ */
371
+ export interface BFFClient {
372
+ /** Projects API */
373
+ readonly projects: ProjectsAPI;
374
+
375
+ /** Deployments API */
376
+ readonly deployments: DeploymentsAPI;
377
+ }
378
+
379
+ /**
380
+ * Create a new BFF client
381
+ *
382
+ * @param config - Client configuration
383
+ * @returns BFFClient instance
384
+ *
385
+ * @example
386
+ * ```typescript
387
+ * const client = createBFFClient({
388
+ * baseUrl: 'http://localhost:11001',
389
+ * authToken: 'your-supabase-jwt',
390
+ * });
391
+ *
392
+ * // Create a project
393
+ * const project = await client.projects.create({
394
+ * name: 'My App',
395
+ * slug: 'my-app',
396
+ * rootPath: '/Users/me/projects/my-app',
397
+ * });
398
+ *
399
+ * // Start a deployment
400
+ * const deployment = await client.deployments.start({
401
+ * projectId: project.id,
402
+ * });
403
+ * ```
404
+ */
405
+ export function createBFFClient(config: BFFClientConfig): BFFClient {
406
+ const timeout = config.timeout ?? 30000;
407
+
408
+ return {
409
+ projects: new ProjectsAPI(config.baseUrl, config.authToken, timeout),
410
+ deployments: new DeploymentsAPI(config.baseUrl, config.authToken, timeout),
411
+ };
412
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * BFF module - API client for BFF Studio endpoints
3
+ *
4
+ * Use this for all write operations (create, update, delete).
5
+ * The BFF uses SQLAlchemy with service_role credentials, which bypasses RLS.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { createBFFClient } from '@agent-foundry/studio/bff';
10
+ *
11
+ * const client = createBFFClient({
12
+ * baseUrl: 'http://localhost:11001',
13
+ * authToken: 'your-supabase-jwt',
14
+ * });
15
+ *
16
+ * // Create a project (write operation via BFF)
17
+ * const project = await client.projects.create({
18
+ * name: 'My App',
19
+ * slug: 'my-app',
20
+ * rootPath: '/path/to/project',
21
+ * });
22
+ * ```
23
+ */
24
+
25
+ export * from './types';
26
+ export {
27
+ createBFFClient,
28
+ BFFAPIError,
29
+ ProjectsAPI,
30
+ DeploymentsAPI,
31
+ } from './client';
32
+ export type { BFFClient } from './client';