@brixel_ai/artifact-sdk 1.0.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/LICENSE +21 -0
- package/README.md +298 -0
- package/dist/index.d.mts +443 -0
- package/dist/index.d.ts +443 -0
- package/dist/index.js +461 -0
- package/dist/index.mjs +428 -0
- package/package.json +67 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brixel UI Task Protocol Types
|
|
3
|
+
*
|
|
4
|
+
* This file defines the postMessage protocol between the Brixel host (chat)
|
|
5
|
+
* and the UI Task iframe.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Render mode determines if the UI Task requires user interaction
|
|
9
|
+
* - "display": Just shows content, no output expected
|
|
10
|
+
* - "interaction": Requires user action, workflow waits for completion
|
|
11
|
+
*/
|
|
12
|
+
type RenderMode = "display" | "interaction";
|
|
13
|
+
/**
|
|
14
|
+
* Context provided by Brixel host to the UI Task
|
|
15
|
+
*/
|
|
16
|
+
interface BrixelContext {
|
|
17
|
+
/** Unique run identifier for this execution */
|
|
18
|
+
runId: string;
|
|
19
|
+
/** Step ID within the workflow (if part of a workflow) */
|
|
20
|
+
stepId?: string;
|
|
21
|
+
/** User identifier */
|
|
22
|
+
userId?: string;
|
|
23
|
+
/** Organization identifier */
|
|
24
|
+
organizationId?: string;
|
|
25
|
+
/** UI preferences */
|
|
26
|
+
theme: "light" | "dark" | "system";
|
|
27
|
+
locale: string;
|
|
28
|
+
/** Conversation ID for API calls (optional) */
|
|
29
|
+
conversationId?: string;
|
|
30
|
+
/** API token passed by parent for authenticated requests (recommended over cookies) */
|
|
31
|
+
apiToken?: string;
|
|
32
|
+
/** Optional custom API base URL (for development/testing) */
|
|
33
|
+
apiBaseUrl?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Artifact manifest schema
|
|
37
|
+
*/
|
|
38
|
+
interface ArtifactManifest {
|
|
39
|
+
id: string;
|
|
40
|
+
version: string;
|
|
41
|
+
type: "ui_component";
|
|
42
|
+
name: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
renderMode: RenderMode;
|
|
45
|
+
entry: string;
|
|
46
|
+
inputSchema?: Record<string, unknown>;
|
|
47
|
+
outputSchema?: Record<string, unknown>;
|
|
48
|
+
ui?: {
|
|
49
|
+
height?: "auto" | number;
|
|
50
|
+
minHeight?: number;
|
|
51
|
+
maxHeight?: number;
|
|
52
|
+
preferredWidth?: "message" | "full" | number;
|
|
53
|
+
};
|
|
54
|
+
permissions?: {
|
|
55
|
+
network?: string[];
|
|
56
|
+
files?: boolean;
|
|
57
|
+
clipboard?: boolean;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* INIT: Sent by host when iframe is ready to receive data
|
|
62
|
+
*/
|
|
63
|
+
interface InitMessage<TInputs = unknown> {
|
|
64
|
+
type: "BRIXEL_INIT";
|
|
65
|
+
payload: {
|
|
66
|
+
runId: string;
|
|
67
|
+
inputs: TInputs;
|
|
68
|
+
context: BrixelContext;
|
|
69
|
+
renderMode: RenderMode;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* UPDATE_INPUTS: Sent when inputs change during execution
|
|
74
|
+
*/
|
|
75
|
+
interface UpdateInputsMessage<TInputs = unknown> {
|
|
76
|
+
type: "BRIXEL_UPDATE_INPUTS";
|
|
77
|
+
payload: {
|
|
78
|
+
runId: string;
|
|
79
|
+
inputs: Partial<TInputs>;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* DESTROY: Sent when the UI Task should clean up
|
|
84
|
+
*/
|
|
85
|
+
interface DestroyMessage {
|
|
86
|
+
type: "BRIXEL_DESTROY";
|
|
87
|
+
payload: {
|
|
88
|
+
runId: string;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* UPDATE_THEME: Sent when the host theme changes
|
|
93
|
+
*/
|
|
94
|
+
interface UpdateThemeMessage {
|
|
95
|
+
type: "BRIXEL_UPDATE_THEME";
|
|
96
|
+
payload: {
|
|
97
|
+
runId: string;
|
|
98
|
+
theme: BrixelContext["theme"];
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* UPDATE_LOCALE: Sent when the host locale changes
|
|
103
|
+
*/
|
|
104
|
+
interface UpdateLocaleMessage {
|
|
105
|
+
type: "BRIXEL_UPDATE_LOCALE";
|
|
106
|
+
payload: {
|
|
107
|
+
runId: string;
|
|
108
|
+
locale: string;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
type HostToIframeMessage<TInputs = unknown> = InitMessage<TInputs> | UpdateInputsMessage<TInputs> | DestroyMessage | UpdateThemeMessage | UpdateLocaleMessage;
|
|
112
|
+
/**
|
|
113
|
+
* READY: Iframe signals it's ready to receive INIT
|
|
114
|
+
*/
|
|
115
|
+
interface ReadyMessage {
|
|
116
|
+
type: "BRIXEL_READY";
|
|
117
|
+
payload: {
|
|
118
|
+
version: string;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* RESIZE: Request height change
|
|
123
|
+
*/
|
|
124
|
+
interface ResizeMessage {
|
|
125
|
+
type: "BRIXEL_RESIZE";
|
|
126
|
+
payload: {
|
|
127
|
+
runId: string;
|
|
128
|
+
height: number | "auto";
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* COMPLETE: Task finished with output (for interaction mode)
|
|
133
|
+
*/
|
|
134
|
+
interface CompleteMessage<TOutput = unknown> {
|
|
135
|
+
type: "BRIXEL_COMPLETE";
|
|
136
|
+
payload: {
|
|
137
|
+
runId: string;
|
|
138
|
+
output: TOutput;
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* CANCEL: User cancelled the task
|
|
143
|
+
*/
|
|
144
|
+
interface CancelMessage {
|
|
145
|
+
type: "BRIXEL_CANCEL";
|
|
146
|
+
payload: {
|
|
147
|
+
runId: string;
|
|
148
|
+
reason?: string;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* ERROR: An error occurred in the UI Task
|
|
153
|
+
*/
|
|
154
|
+
interface ErrorMessage {
|
|
155
|
+
type: "BRIXEL_ERROR";
|
|
156
|
+
payload: {
|
|
157
|
+
runId: string;
|
|
158
|
+
error: {
|
|
159
|
+
code: string;
|
|
160
|
+
message: string;
|
|
161
|
+
details?: unknown;
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* LOG: Debug log from iframe (captured by host in dev mode)
|
|
167
|
+
*/
|
|
168
|
+
interface LogMessage {
|
|
169
|
+
type: "BRIXEL_LOG";
|
|
170
|
+
payload: {
|
|
171
|
+
runId: string;
|
|
172
|
+
level: "debug" | "info" | "warn" | "error";
|
|
173
|
+
message: string;
|
|
174
|
+
data?: unknown;
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
type IframeToHostMessage<TOutput = unknown> = ReadyMessage | ResizeMessage | CompleteMessage<TOutput> | CancelMessage | ErrorMessage | LogMessage;
|
|
178
|
+
type TaskStatus = "initializing" | "ready" | "completed" | "cancelled" | "error";
|
|
179
|
+
interface UseBrixelTaskResult<TInputs, TOutput> {
|
|
180
|
+
/** Current inputs from the host */
|
|
181
|
+
inputs: TInputs | null;
|
|
182
|
+
/** Brixel context (user, theme, locale, etc.) */
|
|
183
|
+
context: BrixelContext | null;
|
|
184
|
+
/** Current task status */
|
|
185
|
+
status: TaskStatus;
|
|
186
|
+
/** Render mode of this task */
|
|
187
|
+
renderMode: RenderMode | null;
|
|
188
|
+
/** Run ID for this execution */
|
|
189
|
+
runId: string | null;
|
|
190
|
+
/** Complete the task with output (required for interaction mode) */
|
|
191
|
+
complete: (output: TOutput) => void;
|
|
192
|
+
/** Cancel the task */
|
|
193
|
+
cancel: (reason?: string) => void;
|
|
194
|
+
/** Request height resize */
|
|
195
|
+
setHeight: (height: number | "auto") => void;
|
|
196
|
+
/** Send a log message to the host */
|
|
197
|
+
log: (level: "debug" | "info" | "warn" | "error", message: string, data?: unknown) => void;
|
|
198
|
+
/** Whether running inside Brixel iframe */
|
|
199
|
+
isEmbedded: boolean;
|
|
200
|
+
/** Execute another UI Task (bound to current context) */
|
|
201
|
+
executeTask: <TTaskOutput = unknown>(params: Omit<ExecuteTaskParams, "conversationId" | "apiToken" | "apiBaseUrl">) => Promise<ExecuteTaskResponse<TTaskOutput>>;
|
|
202
|
+
}
|
|
203
|
+
interface UseBrixelTaskOptions {
|
|
204
|
+
/** Target origin for postMessage (default: "*", should be restricted in production) */
|
|
205
|
+
targetOrigin?: string;
|
|
206
|
+
/** Callback when inputs are updated */
|
|
207
|
+
onInputsUpdate?: (inputs: unknown) => void;
|
|
208
|
+
/** Callback before destroy */
|
|
209
|
+
onDestroy?: () => void;
|
|
210
|
+
/** Enable debug logging */
|
|
211
|
+
debug?: boolean;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Parameters for executing a UI Task via the API
|
|
215
|
+
*/
|
|
216
|
+
interface ExecuteTaskParams {
|
|
217
|
+
/** UUID of the task to execute */
|
|
218
|
+
taskUuid: string;
|
|
219
|
+
/** Input values for the task */
|
|
220
|
+
inputs: Record<string, unknown>;
|
|
221
|
+
/** Optional conversation ID for x-conversation-id header */
|
|
222
|
+
conversationId?: string;
|
|
223
|
+
/** Optional API token (if not provided, uses credentials: 'include' as fallback) */
|
|
224
|
+
apiToken?: string;
|
|
225
|
+
/** Optional custom API base URL (auto-detects dev/prod if not provided) */
|
|
226
|
+
apiBaseUrl?: string;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Response from the execute task API
|
|
230
|
+
*/
|
|
231
|
+
interface ExecuteTaskResponse<TOutput = unknown> {
|
|
232
|
+
success: boolean;
|
|
233
|
+
data?: TOutput;
|
|
234
|
+
error?: {
|
|
235
|
+
code: string;
|
|
236
|
+
message: string;
|
|
237
|
+
details?: unknown;
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Main hook for building Brixel UI Tasks
|
|
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
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
declare function useBrixelArtifact<TInputs = unknown, TOutput = unknown>(options?: UseBrixelTaskOptions): UseBrixelTaskResult<TInputs, TOutput>;
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Execute a UI Task via the Brixel API
|
|
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
|
|
322
|
+
*/
|
|
323
|
+
declare function executeTask<TOutput = unknown>(params: ExecuteTaskParams): Promise<ExecuteTaskResponse<TOutput>>;
|
|
324
|
+
/**
|
|
325
|
+
* Create an executeTask function bound to a specific context
|
|
326
|
+
*
|
|
327
|
+
* This is useful when you want to reuse the same auth context
|
|
328
|
+
* for multiple task executions.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```tsx
|
|
332
|
+
* const { context } = useBrixelArtifact();
|
|
333
|
+
* const boundExecuteTask = createExecuteTask({
|
|
334
|
+
* apiToken: context?.apiToken,
|
|
335
|
+
* conversationId: context?.conversationId
|
|
336
|
+
* });
|
|
337
|
+
*
|
|
338
|
+
* // Now you can call it without passing auth each time
|
|
339
|
+
* const result = await boundExecuteTask({
|
|
340
|
+
* taskUuid: "task-123",
|
|
341
|
+
* inputs: { foo: "bar" }
|
|
342
|
+
* });
|
|
343
|
+
* ```
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```tsx
|
|
347
|
+
* // Or use the executeTask from the hook directly (recommended)
|
|
348
|
+
* const { executeTask } = useBrixelArtifact();
|
|
349
|
+
*
|
|
350
|
+
* const result = await executeTask({
|
|
351
|
+
* taskUuid: "task-123",
|
|
352
|
+
* inputs: { foo: "bar" }
|
|
353
|
+
* });
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
declare function createExecuteTask(contextAuth?: {
|
|
357
|
+
apiToken?: string;
|
|
358
|
+
conversationId?: string;
|
|
359
|
+
apiBaseUrl?: string;
|
|
360
|
+
}): <TOutput = unknown>(params: Omit<ExecuteTaskParams, "conversationId" | "apiToken" | "apiBaseUrl">) => Promise<ExecuteTaskResponse<TOutput>>;
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Development tools for testing UI Tasks outside of Brixel
|
|
364
|
+
*
|
|
365
|
+
* These utilities help simulate the Brixel host environment during development
|
|
366
|
+
*/
|
|
367
|
+
/**
|
|
368
|
+
* Default mock context for development
|
|
369
|
+
*/
|
|
370
|
+
declare const mockContext: BrixelContext;
|
|
371
|
+
/**
|
|
372
|
+
* Simulate the Brixel host sending an INIT message
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
* ```tsx
|
|
376
|
+
* // In your main.tsx or App.tsx for development
|
|
377
|
+
* if (import.meta.env.DEV) {
|
|
378
|
+
* simulateBrixelInit({
|
|
379
|
+
* title: "Test Survey",
|
|
380
|
+
* questions: [
|
|
381
|
+
* { id: "q1", text: "How are you?", options: ["Good", "Bad"] }
|
|
382
|
+
* ]
|
|
383
|
+
* });
|
|
384
|
+
* }
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
declare function simulateBrixelInit<TInputs = unknown>(inputs: TInputs, options?: {
|
|
388
|
+
runId?: string;
|
|
389
|
+
renderMode?: RenderMode;
|
|
390
|
+
context?: Partial<BrixelContext>;
|
|
391
|
+
delay?: number;
|
|
392
|
+
}): void;
|
|
393
|
+
/**
|
|
394
|
+
* Listen for messages from the UI Task (useful for debugging)
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* ```tsx
|
|
398
|
+
* useEffect(() => {
|
|
399
|
+
* const cleanup = listenToUITaskMessages((message) => {
|
|
400
|
+
* console.debug("Artifact sent:", message);
|
|
401
|
+
* });
|
|
402
|
+
* return cleanup;
|
|
403
|
+
* }, []);
|
|
404
|
+
* ```
|
|
405
|
+
*/
|
|
406
|
+
declare function listenToUITaskMessages(callback: (message: unknown) => void): () => void;
|
|
407
|
+
/**
|
|
408
|
+
* Create a mock Brixel host for development
|
|
409
|
+
*
|
|
410
|
+
* @example
|
|
411
|
+
* ```tsx
|
|
412
|
+
* const host = createMockBrixelHost({
|
|
413
|
+
* onComplete: (output) => console.debug("Completed:", output),
|
|
414
|
+
* onCancel: (reason) => console.debug("Cancelled:", reason),
|
|
415
|
+
* });
|
|
416
|
+
*
|
|
417
|
+
* // Send init
|
|
418
|
+
* host.init({ title: "Test" });
|
|
419
|
+
*
|
|
420
|
+
* // Cleanup
|
|
421
|
+
* host.destroy();
|
|
422
|
+
* ```
|
|
423
|
+
*/
|
|
424
|
+
declare function createMockBrixelHost<TInputs = unknown, TOutput = unknown>(options: {
|
|
425
|
+
onReady?: (version: string) => void;
|
|
426
|
+
onComplete?: (output: TOutput) => void;
|
|
427
|
+
onCancel?: (reason?: string) => void;
|
|
428
|
+
onResize?: (height: number | "auto") => void;
|
|
429
|
+
onLog?: (level: string, message: string, data?: unknown) => void;
|
|
430
|
+
onError?: (error: {
|
|
431
|
+
code: string;
|
|
432
|
+
message: string;
|
|
433
|
+
details?: unknown;
|
|
434
|
+
}) => void;
|
|
435
|
+
}): {
|
|
436
|
+
init(inputs: TInputs, runId?: string, renderMode?: RenderMode): void;
|
|
437
|
+
updateInputs(inputs: Partial<TInputs>): void;
|
|
438
|
+
destroy(): void;
|
|
439
|
+
updateTheme(theme: BrixelContext["theme"]): void;
|
|
440
|
+
updateLocale(locale: string): void;
|
|
441
|
+
};
|
|
442
|
+
|
|
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 };
|