@brixel_ai/artifact-sdk 1.0.0 → 1.0.1
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 +88 -9
- package/dist/index.d.mts +125 -116
- package/dist/index.d.ts +125 -116
- package/dist/index.js +316 -119
- package/dist/index.mjs +313 -120
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,9 +78,16 @@ interface UseBrixelTaskOptions {
|
|
|
78
78
|
onInputsUpdate?: (inputs) => void; // Callback when inputs change
|
|
79
79
|
onDestroy?: () => void; // Callback before cleanup
|
|
80
80
|
debug?: boolean; // Enable debug logging
|
|
81
|
+
autoResize?: boolean; // Auto-send BRIXEL_RESIZE based on content height (default: false)
|
|
81
82
|
}
|
|
82
83
|
```
|
|
83
84
|
|
|
85
|
+
### Full Parent Space vs `setHeight`
|
|
86
|
+
|
|
87
|
+
If your SDK components must always fill the space allocated by the parent, keep `autoResize` disabled (default) and use CSS layout like `height: 100%` in your component root.
|
|
88
|
+
|
|
89
|
+
Use `setHeight` (or `autoResize: true`) only when the iframe height must be content-driven.
|
|
90
|
+
|
|
84
91
|
## Development Mode
|
|
85
92
|
|
|
86
93
|
Test your UI Task locally without Brixel:
|
|
@@ -179,7 +186,7 @@ function MyUITask() {
|
|
|
179
186
|
|
|
180
187
|
const handleExecuteTask = async () => {
|
|
181
188
|
const result = await executeTask({
|
|
182
|
-
|
|
189
|
+
taskId: "78c2482f-b47d-461c-9fd0-509476687be9",
|
|
183
190
|
inputs: { name: "value" },
|
|
184
191
|
});
|
|
185
192
|
|
|
@@ -196,10 +203,7 @@ function MyUITask() {
|
|
|
196
203
|
|
|
197
204
|
### Authentication
|
|
198
205
|
|
|
199
|
-
The
|
|
200
|
-
|
|
201
|
-
1. **API Token via postMessage** (RECOMMENDED): The parent interface passes the token via the INIT message
|
|
202
|
-
2. **Cookies fallback**: Uses `credentials: 'include'` if no token provided
|
|
206
|
+
The SDK uses Bearer token authentication. The parent interface should pass `apiToken` via the INIT message context.
|
|
203
207
|
|
|
204
208
|
#### Passing Token from Parent
|
|
205
209
|
|
|
@@ -213,6 +217,7 @@ iframe.contentWindow.postMessage({
|
|
|
213
217
|
runId: 'run-123',
|
|
214
218
|
inputs: { /* ... */ },
|
|
215
219
|
context: {
|
|
220
|
+
organizationId: 'org-123',
|
|
216
221
|
apiToken: authToken,
|
|
217
222
|
// ... other context fields
|
|
218
223
|
}
|
|
@@ -227,7 +232,7 @@ const { executeTask, context } = useBrixelArtifact();
|
|
|
227
232
|
|
|
228
233
|
// Token from context is automatically used
|
|
229
234
|
await executeTask({
|
|
230
|
-
|
|
235
|
+
taskId: "task-uuid",
|
|
231
236
|
inputs: {}
|
|
232
237
|
});
|
|
233
238
|
|
|
@@ -237,16 +242,90 @@ await executeTask({
|
|
|
237
242
|
|
|
238
243
|
The SDK automatically detects your environment and uses the appropriate API:
|
|
239
244
|
|
|
240
|
-
- **Development** (localhost): `http://localhost:8000
|
|
241
|
-
- **Production**: `https://
|
|
245
|
+
- **Development** (localhost): `http://localhost:8000`
|
|
246
|
+
- **Production**: `https://platform.brixel.ai`
|
|
242
247
|
|
|
243
248
|
When running on localhost, you'll see:
|
|
244
249
|
```
|
|
245
|
-
[Brixel SDK] Using API URL: http://localhost:8000
|
|
250
|
+
[Brixel SDK] Using API URL: http://localhost:8000
|
|
246
251
|
```
|
|
247
252
|
|
|
248
253
|
See [DEVELOPMENT.md](./DEVELOPMENT.md) for details on local development setup.
|
|
249
254
|
|
|
255
|
+
## Uploading Files
|
|
256
|
+
|
|
257
|
+
The SDK provides an `uploadFile` function to upload files to Brixel using:
|
|
258
|
+
|
|
259
|
+
- Endpoint: `POST /v1/files/`
|
|
260
|
+
- Form fields:
|
|
261
|
+
- `file`
|
|
262
|
+
- `visibility` (always forced to `"user"` by the SDK)
|
|
263
|
+
- Header (optional): `X-Organization-Id`
|
|
264
|
+
|
|
265
|
+
```tsx
|
|
266
|
+
import { useBrixelArtifact } from "@brixel_ai/artifact-sdk";
|
|
267
|
+
|
|
268
|
+
function MyUITask() {
|
|
269
|
+
const { uploadFile } = useBrixelArtifact();
|
|
270
|
+
|
|
271
|
+
const handleUpload = async (file: File) => {
|
|
272
|
+
const result = await uploadFile({
|
|
273
|
+
file,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
if (!result.success) {
|
|
277
|
+
console.error("Upload error:", result.error);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
console.debug("Uploaded file:", result.data);
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
return <input type="file" onChange={(e) => e.target.files?.[0] && handleUpload(e.target.files[0])} />;
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Getting File Content
|
|
289
|
+
|
|
290
|
+
The SDK provides `getFileContent` to retrieve inline file content:
|
|
291
|
+
|
|
292
|
+
- Endpoint: `GET /v1/files/{brixel_file_id}/content`
|
|
293
|
+
- Headers (optional):
|
|
294
|
+
- `X-Organization-Id`
|
|
295
|
+
- `X-Conversation-Id`
|
|
296
|
+
- `If-None-Match`
|
|
297
|
+
- `If-Modified-Since`
|
|
298
|
+
|
|
299
|
+
```tsx
|
|
300
|
+
import { useBrixelArtifact } from "@brixel_ai/artifact-sdk";
|
|
301
|
+
|
|
302
|
+
function MyUITask() {
|
|
303
|
+
const { getFileContent } = useBrixelArtifact();
|
|
304
|
+
|
|
305
|
+
const handlePreview = async (brixelFileId: string) => {
|
|
306
|
+
const result = await getFileContent({
|
|
307
|
+
brixelFileId,
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
if (!result.success) {
|
|
311
|
+
console.error("Get content error:", result.error);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (result.notModified) {
|
|
316
|
+
console.debug("File not modified");
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (!result.data) return;
|
|
321
|
+
const url = URL.createObjectURL(result.data.blob);
|
|
322
|
+
console.debug("Preview URL:", url, "content-type:", result.data.contentType);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
return <button onClick={() => handlePreview("your-brixel-file-id")}>Preview</button>;
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
250
329
|
## PostMessage Protocol
|
|
251
330
|
|
|
252
331
|
The SDK handles the following message types automatically:
|
package/dist/index.d.mts
CHANGED
|
@@ -198,7 +198,18 @@ interface UseBrixelTaskResult<TInputs, TOutput> {
|
|
|
198
198
|
/** Whether running inside Brixel iframe */
|
|
199
199
|
isEmbedded: boolean;
|
|
200
200
|
/** Execute another UI Task (bound to current context) */
|
|
201
|
-
executeTask: <TTaskOutput = unknown>(params: Omit<ExecuteTaskParams, "conversationId" | "apiToken" | "apiBaseUrl">
|
|
201
|
+
executeTask: <TTaskOutput = unknown>(params: Omit<ExecuteTaskParams, "conversationId" | "apiToken" | "apiBaseUrl"> & {
|
|
202
|
+
organizationId?: string;
|
|
203
|
+
}) => Promise<ExecuteTaskResponse<TTaskOutput>>;
|
|
204
|
+
/** Upload a file to Brixel (visibility is always forced to "user") */
|
|
205
|
+
uploadFile: <TFileOutput = InternalFilePublicOut>(params: Omit<UploadFileParams, "organizationId" | "apiToken" | "apiBaseUrl"> & {
|
|
206
|
+
organizationId?: string;
|
|
207
|
+
}) => Promise<UploadFileResponse<TFileOutput>>;
|
|
208
|
+
/** Get inline content of a Brixel file by id */
|
|
209
|
+
getFileContent: <TContentOutput = FileContentData>(params: Omit<GetFileContentParams, "organizationId" | "conversationId" | "apiToken" | "apiBaseUrl"> & {
|
|
210
|
+
organizationId?: string;
|
|
211
|
+
conversationId?: string;
|
|
212
|
+
}) => Promise<GetFileContentResponse<TContentOutput>>;
|
|
202
213
|
}
|
|
203
214
|
interface UseBrixelTaskOptions {
|
|
204
215
|
/** Target origin for postMessage (default: "*", should be restricted in production) */
|
|
@@ -209,18 +220,22 @@ interface UseBrixelTaskOptions {
|
|
|
209
220
|
onDestroy?: () => void;
|
|
210
221
|
/** Enable debug logging */
|
|
211
222
|
debug?: boolean;
|
|
223
|
+
/** Auto-send BRIXEL_RESIZE based on document.body size changes */
|
|
224
|
+
autoResize?: boolean;
|
|
212
225
|
}
|
|
213
226
|
/**
|
|
214
227
|
* Parameters for executing a UI Task via the API
|
|
215
228
|
*/
|
|
216
229
|
interface ExecuteTaskParams {
|
|
217
|
-
/**
|
|
218
|
-
|
|
230
|
+
/** ID of the organization owning the task */
|
|
231
|
+
organizationId: string;
|
|
232
|
+
/** ID of the task to execute */
|
|
233
|
+
taskId: string;
|
|
219
234
|
/** Input values for the task */
|
|
220
235
|
inputs: Record<string, unknown>;
|
|
221
236
|
/** Optional conversation ID for x-conversation-id header */
|
|
222
237
|
conversationId?: string;
|
|
223
|
-
/**
|
|
238
|
+
/** API token used as Bearer token for API requests */
|
|
224
239
|
apiToken?: string;
|
|
225
240
|
/** Optional custom API base URL (auto-detects dev/prod if not provided) */
|
|
226
241
|
apiBaseUrl?: string;
|
|
@@ -237,127 +252,121 @@ interface ExecuteTaskResponse<TOutput = unknown> {
|
|
|
237
252
|
details?: unknown;
|
|
238
253
|
};
|
|
239
254
|
}
|
|
240
|
-
|
|
241
255
|
/**
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
* @example
|
|
245
|
-
* ```tsx
|
|
246
|
-
* import { useBrixelArtifact } from "@brixel/artifact-sdk";
|
|
247
|
-
*
|
|
248
|
-
* interface Inputs {
|
|
249
|
-
* title: string;
|
|
250
|
-
* options: string[];
|
|
251
|
-
* }
|
|
252
|
-
*
|
|
253
|
-
* interface Output {
|
|
254
|
-
* selectedOption: string;
|
|
255
|
-
* }
|
|
256
|
-
*
|
|
257
|
-
* function MyUITask() {
|
|
258
|
-
* const { inputs, complete, cancel, context } = useBrixelArtifact<Inputs, Output>();
|
|
259
|
-
*
|
|
260
|
-
* if (!inputs) return <div>Loading...</div>;
|
|
261
|
-
*
|
|
262
|
-
* return (
|
|
263
|
-
* <div>
|
|
264
|
-
* <h1>{inputs.title}</h1>
|
|
265
|
-
* {inputs.options.map(opt => (
|
|
266
|
-
* <button key={opt} onClick={() => complete({ selectedOption: opt })}>
|
|
267
|
-
* {opt}
|
|
268
|
-
* </button>
|
|
269
|
-
* ))}
|
|
270
|
-
* <button onClick={() => cancel()}>Cancel</button>
|
|
271
|
-
* </div>
|
|
272
|
-
* );
|
|
273
|
-
* }
|
|
274
|
-
* ```
|
|
256
|
+
* Parameters for uploading a file to Brixel
|
|
275
257
|
*/
|
|
276
|
-
|
|
277
|
-
|
|
258
|
+
interface UploadFileParams {
|
|
259
|
+
/** File to upload */
|
|
260
|
+
file: File;
|
|
261
|
+
/** Optional organization ID sent as X-Organization-Id header */
|
|
262
|
+
organizationId?: string;
|
|
263
|
+
/** API token used as Bearer token for API requests */
|
|
264
|
+
apiToken?: string;
|
|
265
|
+
/** Optional custom API base URL (auto-detects dev/prod if not provided) */
|
|
266
|
+
apiBaseUrl?: string;
|
|
267
|
+
}
|
|
278
268
|
/**
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
* This function allows UI Tasks to programmatically execute other UI Tasks.
|
|
282
|
-
*
|
|
283
|
-
* **API URL auto-detection:**
|
|
284
|
-
* - Development (localhost): http://localhost:8000/backoffice/ui-components
|
|
285
|
-
* - Production: https://api.brixel.ai/backoffice/ui-components
|
|
286
|
-
* - Can be overridden via `apiBaseUrl` parameter
|
|
287
|
-
*
|
|
288
|
-
* **Authentication strategy (in order of priority):**
|
|
289
|
-
* 1. **API Token from context** (RECOMMENDED): Passed via postMessage from parent
|
|
290
|
-
* - More secure and explicit
|
|
291
|
-
* - Parent has full control over the token
|
|
292
|
-
* 2. **Cookies fallback**: Uses credentials: 'include' if no token provided
|
|
293
|
-
* - Works for same-domain scenarios (*.brixel.ai)
|
|
294
|
-
*
|
|
295
|
-
* @example
|
|
296
|
-
* ```tsx
|
|
297
|
-
* import { executeTask } from "@brixel/artifact-sdk";
|
|
298
|
-
*
|
|
299
|
-
* // Recommended: Use token from context (passed by parent via postMessage)
|
|
300
|
-
* const result = await executeTask({
|
|
301
|
-
* taskUuid: "task-123-456",
|
|
302
|
-
* inputs: { name: "John", email: "john@example.com" },
|
|
303
|
-
* apiToken: context?.apiToken, // Token passed by parent
|
|
304
|
-
* });
|
|
305
|
-
*
|
|
306
|
-
* // Or let the hook bind it automatically
|
|
307
|
-
* const { executeTask } = useBrixelArtifact();
|
|
308
|
-
* const result = await executeTask({
|
|
309
|
-
* taskUuid: "task-123-456",
|
|
310
|
-
* inputs: { name: "John", email: "john@example.com" },
|
|
311
|
-
* });
|
|
312
|
-
*
|
|
313
|
-
* if (result.success) {
|
|
314
|
-
* console.debug("Task executed:", result.data);
|
|
315
|
-
* } else {
|
|
316
|
-
* console.error("Error:", result.error);
|
|
317
|
-
* }
|
|
318
|
-
* ```
|
|
319
|
-
*
|
|
320
|
-
* @param params - Parameters for executing the task
|
|
321
|
-
* @returns Promise with the execution result
|
|
269
|
+
* Mime type returned by Brixel for internal files.
|
|
270
|
+
* Kept as `string` because backend enum values may evolve.
|
|
322
271
|
*/
|
|
323
|
-
|
|
272
|
+
type InternalFileMimeType = string;
|
|
324
273
|
/**
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
*
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
* const result = await executeTask({
|
|
351
|
-
* taskUuid: "task-123",
|
|
352
|
-
* inputs: { foo: "bar" }
|
|
353
|
-
* });
|
|
354
|
-
* ```
|
|
274
|
+
* Public schema for internal file output.
|
|
275
|
+
* Mirrors backend `InternalFilePublicOut`.
|
|
276
|
+
*/
|
|
277
|
+
interface InternalFilePublicOut {
|
|
278
|
+
brixel_file_id: string;
|
|
279
|
+
name: string;
|
|
280
|
+
mime_type: InternalFileMimeType;
|
|
281
|
+
size: number;
|
|
282
|
+
expires_at: string | null;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Response from the upload file API
|
|
286
|
+
*/
|
|
287
|
+
interface UploadFileResponse<TOutput = InternalFilePublicOut> {
|
|
288
|
+
success: boolean;
|
|
289
|
+
data?: TOutput;
|
|
290
|
+
error?: {
|
|
291
|
+
code: string;
|
|
292
|
+
message: string;
|
|
293
|
+
details?: unknown;
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Returned file content payload
|
|
355
298
|
*/
|
|
299
|
+
interface FileContentData {
|
|
300
|
+
blob: Blob;
|
|
301
|
+
contentType: string | null;
|
|
302
|
+
contentLength?: number;
|
|
303
|
+
etag?: string | null;
|
|
304
|
+
lastModified?: string | null;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Parameters for getting file content from Brixel
|
|
308
|
+
*/
|
|
309
|
+
interface GetFileContentParams {
|
|
310
|
+
/** Brixel file id */
|
|
311
|
+
brixelFileId: string;
|
|
312
|
+
/** Optional organization ID sent as X-Organization-Id header */
|
|
313
|
+
organizationId?: string;
|
|
314
|
+
/** Optional conversation ID sent as X-Conversation-Id header */
|
|
315
|
+
conversationId?: string;
|
|
316
|
+
/** API token used as Bearer token for API requests */
|
|
317
|
+
apiToken?: string;
|
|
318
|
+
/** Optional custom API base URL (auto-detects dev/prod if not provided) */
|
|
319
|
+
apiBaseUrl?: string;
|
|
320
|
+
/** Optional conditional request header */
|
|
321
|
+
ifNoneMatch?: string;
|
|
322
|
+
/** Optional conditional request header */
|
|
323
|
+
ifModifiedSince?: string;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Response from the get file content API
|
|
327
|
+
*/
|
|
328
|
+
interface GetFileContentResponse<TOutput = FileContentData> {
|
|
329
|
+
success: boolean;
|
|
330
|
+
notModified?: boolean;
|
|
331
|
+
data?: TOutput;
|
|
332
|
+
error?: {
|
|
333
|
+
code: string;
|
|
334
|
+
message: string;
|
|
335
|
+
details?: unknown;
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
declare function useBrixelArtifact<TInputs = unknown, TOutput = unknown>(options?: UseBrixelTaskOptions): UseBrixelTaskResult<TInputs, TOutput>;
|
|
340
|
+
|
|
341
|
+
declare function executeTask<TOutput = unknown>(params: ExecuteTaskParams): Promise<ExecuteTaskResponse<TOutput>>;
|
|
356
342
|
declare function createExecuteTask(contextAuth?: {
|
|
343
|
+
organizationId?: string;
|
|
357
344
|
apiToken?: string;
|
|
358
345
|
conversationId?: string;
|
|
359
346
|
apiBaseUrl?: string;
|
|
360
|
-
}): <TOutput = unknown>(params: Omit<ExecuteTaskParams, "conversationId" | "apiToken" | "apiBaseUrl">
|
|
347
|
+
}): <TOutput = unknown>(params: Omit<ExecuteTaskParams, "conversationId" | "apiToken" | "apiBaseUrl"> & {
|
|
348
|
+
organizationId?: string;
|
|
349
|
+
}) => Promise<ExecuteTaskResponse<TOutput>>;
|
|
350
|
+
|
|
351
|
+
declare function uploadFile<TOutput = InternalFilePublicOut>(params: UploadFileParams): Promise<UploadFileResponse<TOutput>>;
|
|
352
|
+
declare function createUploadFile(contextAuth?: {
|
|
353
|
+
organizationId?: string;
|
|
354
|
+
apiToken?: string;
|
|
355
|
+
apiBaseUrl?: string;
|
|
356
|
+
}): <TOutput = InternalFilePublicOut>(params: Omit<UploadFileParams, "organizationId" | "apiToken" | "apiBaseUrl"> & {
|
|
357
|
+
organizationId?: string;
|
|
358
|
+
}) => Promise<UploadFileResponse<TOutput>>;
|
|
359
|
+
|
|
360
|
+
declare function getFileContent<TOutput = FileContentData>(params: GetFileContentParams): Promise<GetFileContentResponse<TOutput>>;
|
|
361
|
+
declare function createGetFileContent(contextAuth?: {
|
|
362
|
+
organizationId?: string;
|
|
363
|
+
conversationId?: string;
|
|
364
|
+
apiToken?: string;
|
|
365
|
+
apiBaseUrl?: string;
|
|
366
|
+
}): <TOutput = FileContentData>(params: Omit<GetFileContentParams, "organizationId" | "conversationId" | "apiToken" | "apiBaseUrl"> & {
|
|
367
|
+
organizationId?: string;
|
|
368
|
+
conversationId?: string;
|
|
369
|
+
}) => Promise<GetFileContentResponse<TOutput>>;
|
|
361
370
|
|
|
362
371
|
/**
|
|
363
372
|
* Development tools for testing UI Tasks outside of Brixel
|
|
@@ -440,4 +449,4 @@ declare function createMockBrixelHost<TInputs = unknown, TOutput = unknown>(opti
|
|
|
440
449
|
updateLocale(locale: string): void;
|
|
441
450
|
};
|
|
442
451
|
|
|
443
|
-
export { type ArtifactManifest, type BrixelContext, type CancelMessage, type CompleteMessage, type DestroyMessage, type ErrorMessage, type ExecuteTaskParams, type ExecuteTaskResponse, type HostToIframeMessage, type IframeToHostMessage, type InitMessage, type LogMessage, type ReadyMessage, type RenderMode, type ResizeMessage, type TaskStatus, type UpdateInputsMessage, type UpdateLocaleMessage, type UpdateThemeMessage, type UseBrixelTaskOptions, type UseBrixelTaskResult, createExecuteTask, createMockBrixelHost, executeTask, listenToUITaskMessages, mockContext, simulateBrixelInit, useBrixelArtifact };
|
|
452
|
+
export { type ArtifactManifest, type BrixelContext, type CancelMessage, type CompleteMessage, type DestroyMessage, type ErrorMessage, type ExecuteTaskParams, type ExecuteTaskResponse, type FileContentData, type GetFileContentParams, type GetFileContentResponse, type HostToIframeMessage, type IframeToHostMessage, type InitMessage, type InternalFileMimeType, type InternalFilePublicOut, type LogMessage, type ReadyMessage, type RenderMode, type ResizeMessage, type TaskStatus, type UpdateInputsMessage, type UpdateLocaleMessage, type UpdateThemeMessage, type UploadFileParams, type UploadFileResponse, type UseBrixelTaskOptions, type UseBrixelTaskResult, createExecuteTask, createGetFileContent, createMockBrixelHost, createUploadFile, executeTask, getFileContent, listenToUITaskMessages, mockContext, simulateBrixelInit, uploadFile, useBrixelArtifact };
|