@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.
@@ -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 };