@brixel_ai/artifact-sdk 1.0.3 → 1.0.5

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 CHANGED
@@ -157,28 +157,30 @@ interface BrixelContext {
157
157
  ## Executing Other UI Tasks
158
158
 
159
159
  The SDK allows UI Tasks to execute other UI Tasks programmatically using the `executeTask` function.
160
- On success, `executeTask` returns the action `result` directly. On failure, it returns an `ExecuteTaskError`.
160
+ `executeTask` returns `{ success, data }`:
161
+ - `success: true` => `data` is the task result
162
+ - `success: false` => `data` is an `ExecuteTaskError`
161
163
 
162
164
  ### Basic Usage
163
165
 
164
166
  ```tsx
165
- import { isExecuteTaskError, useBrixelArtifact } from "@brixel_ai/artifact-sdk";
167
+ import { useBrixelArtifact } from "@brixel_ai/artifact-sdk";
166
168
 
167
169
  function MyUITask() {
168
170
  const { executeTask } = useBrixelArtifact();
169
171
 
170
172
  const handleExecuteTask = async () => {
171
- const result = await executeTask<{ message: string }>({
173
+ const response = await executeTask<{ message: string }>({
172
174
  taskId: "78c2482f-b47d-461c-9fd0-509476687be9",
173
175
  inputs: { name: "value" },
174
176
  });
175
177
 
176
- if (isExecuteTaskError(result)) {
177
- console.error("Error:", result);
178
+ if (!response.success) {
179
+ console.error("Error:", response.data);
178
180
  return;
179
181
  }
180
182
 
181
- console.debug("Task executed:", result);
183
+ console.debug("Task executed:", response.data);
182
184
  };
183
185
 
184
186
  return <button onClick={handleExecuteTask}>Execute Task</button>;
package/dist/index.d.mts CHANGED
@@ -249,11 +249,23 @@ interface ExecuteTaskError {
249
249
  details?: unknown;
250
250
  }
251
251
  /**
252
- * Return value from executeTask:
253
- * - success: returns task result directly
254
- * - failure: returns ExecuteTaskError
252
+ * Successful executeTask response.
255
253
  */
256
- type ExecuteTaskResponse<TOutput = unknown> = TOutput | ExecuteTaskError;
254
+ interface ExecuteTaskSuccessResponse<TOutput = unknown> {
255
+ success: true;
256
+ data: TOutput;
257
+ }
258
+ /**
259
+ * Failed executeTask response.
260
+ */
261
+ interface ExecuteTaskFailureResponse {
262
+ success: false;
263
+ data: ExecuteTaskError;
264
+ }
265
+ /**
266
+ * Return value from executeTask.
267
+ */
268
+ type ExecuteTaskResponse<TOutput = unknown> = ExecuteTaskSuccessResponse<TOutput> | ExecuteTaskFailureResponse;
257
269
  /**
258
270
  * Parameters for uploading a file to Brixel
259
271
  */
@@ -349,7 +361,7 @@ declare function createExecuteTask(contextAuth?: {
349
361
  }): <TOutput = unknown>(params: Omit<ExecuteTaskParams, "conversationId" | "apiToken" | "apiBaseUrl"> & {
350
362
  organizationId?: string;
351
363
  }) => Promise<ExecuteTaskResponse<TOutput>>;
352
- declare function isExecuteTaskError(value: unknown): value is ExecuteTaskError;
364
+ declare function isExecuteTaskError(value: unknown): value is ExecuteTaskError | ExecuteTaskFailureResponse;
353
365
 
354
366
  declare function uploadFile<TOutput = InternalFilePublicOut>(params: UploadFileParams): Promise<UploadFileResponse<TOutput>>;
355
367
  declare function createUploadFile(contextAuth?: {
@@ -413,4 +425,4 @@ declare function simulateBrixelInit<TInputs = unknown>(inputs: TInputs, options?
413
425
  */
414
426
  declare function listenToUITaskMessages(callback: (message: unknown) => void): () => void;
415
427
 
416
- export { type ArtifactManifest, type BrixelContext, type CancelMessage, type CompleteMessage, type DestroyMessage, type ErrorMessage, type ExecuteTaskError, 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, createUploadFile, executeTask, getFileContent, isExecuteTaskError, listenToUITaskMessages, simulateBrixelInit, uploadFile, useBrixelArtifact };
428
+ export { type ArtifactManifest, type BrixelContext, type CancelMessage, type CompleteMessage, type DestroyMessage, type ErrorMessage, type ExecuteTaskError, type ExecuteTaskFailureResponse, type ExecuteTaskParams, type ExecuteTaskResponse, type ExecuteTaskSuccessResponse, 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, createUploadFile, executeTask, getFileContent, isExecuteTaskError, listenToUITaskMessages, simulateBrixelInit, uploadFile, useBrixelArtifact };
package/dist/index.d.ts CHANGED
@@ -249,11 +249,23 @@ interface ExecuteTaskError {
249
249
  details?: unknown;
250
250
  }
251
251
  /**
252
- * Return value from executeTask:
253
- * - success: returns task result directly
254
- * - failure: returns ExecuteTaskError
252
+ * Successful executeTask response.
255
253
  */
256
- type ExecuteTaskResponse<TOutput = unknown> = TOutput | ExecuteTaskError;
254
+ interface ExecuteTaskSuccessResponse<TOutput = unknown> {
255
+ success: true;
256
+ data: TOutput;
257
+ }
258
+ /**
259
+ * Failed executeTask response.
260
+ */
261
+ interface ExecuteTaskFailureResponse {
262
+ success: false;
263
+ data: ExecuteTaskError;
264
+ }
265
+ /**
266
+ * Return value from executeTask.
267
+ */
268
+ type ExecuteTaskResponse<TOutput = unknown> = ExecuteTaskSuccessResponse<TOutput> | ExecuteTaskFailureResponse;
257
269
  /**
258
270
  * Parameters for uploading a file to Brixel
259
271
  */
@@ -349,7 +361,7 @@ declare function createExecuteTask(contextAuth?: {
349
361
  }): <TOutput = unknown>(params: Omit<ExecuteTaskParams, "conversationId" | "apiToken" | "apiBaseUrl"> & {
350
362
  organizationId?: string;
351
363
  }) => Promise<ExecuteTaskResponse<TOutput>>;
352
- declare function isExecuteTaskError(value: unknown): value is ExecuteTaskError;
364
+ declare function isExecuteTaskError(value: unknown): value is ExecuteTaskError | ExecuteTaskFailureResponse;
353
365
 
354
366
  declare function uploadFile<TOutput = InternalFilePublicOut>(params: UploadFileParams): Promise<UploadFileResponse<TOutput>>;
355
367
  declare function createUploadFile(contextAuth?: {
@@ -413,4 +425,4 @@ declare function simulateBrixelInit<TInputs = unknown>(inputs: TInputs, options?
413
425
  */
414
426
  declare function listenToUITaskMessages(callback: (message: unknown) => void): () => void;
415
427
 
416
- export { type ArtifactManifest, type BrixelContext, type CancelMessage, type CompleteMessage, type DestroyMessage, type ErrorMessage, type ExecuteTaskError, 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, createUploadFile, executeTask, getFileContent, isExecuteTaskError, listenToUITaskMessages, simulateBrixelInit, uploadFile, useBrixelArtifact };
428
+ export { type ArtifactManifest, type BrixelContext, type CancelMessage, type CompleteMessage, type DestroyMessage, type ErrorMessage, type ExecuteTaskError, type ExecuteTaskFailureResponse, type ExecuteTaskParams, type ExecuteTaskResponse, type ExecuteTaskSuccessResponse, 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, createUploadFile, executeTask, getFileContent, isExecuteTaskError, listenToUITaskMessages, simulateBrixelInit, uploadFile, useBrixelArtifact };
package/dist/index.js CHANGED
@@ -90,16 +90,16 @@ async function executeTask(params) {
90
90
  debugApiBaseUrl(baseUrl);
91
91
  try {
92
92
  if (!organizationId) {
93
- return {
93
+ return toExecuteTaskFailure({
94
94
  code: "MISSING_ORGANIZATION_ID",
95
95
  message: "organizationId is required to execute a task"
96
- };
96
+ });
97
97
  }
98
98
  if (!taskId) {
99
- return {
99
+ return toExecuteTaskFailure({
100
100
  code: "MISSING_TASK_ID",
101
101
  message: "taskId is required to execute a task"
102
- };
102
+ });
103
103
  }
104
104
  const headers = {
105
105
  "Content-Type": "application/json"
@@ -120,21 +120,22 @@ async function executeTask(params) {
120
120
  body: JSON.stringify({ inputs })
121
121
  }
122
122
  );
123
- const data = await parseJsonOrText(response);
123
+ const rawData = await parseJsonOrText(response);
124
+ const data = decodeBase64BytesPayloads(rawData);
124
125
  if (!response.ok) {
125
- return toHttpError(response, data);
126
+ return toExecuteTaskFailure(toHttpError(response, data));
126
127
  }
127
128
  if (isActionExecutePayload(data)) {
128
129
  if (data.success === false) {
129
- return toActionExecutionError(data);
130
+ return toExecuteTaskFailure(toActionExecutionError(data));
130
131
  }
131
132
  if ("result" in data) {
132
- return data.result;
133
+ return toExecuteTaskSuccess(data.result);
133
134
  }
134
135
  }
135
- return data ?? void 0;
136
+ return toExecuteTaskSuccess(data ?? void 0);
136
137
  } catch (error) {
137
- return toNetworkError(error);
138
+ return toExecuteTaskFailure(toNetworkError(error));
138
139
  }
139
140
  }
140
141
  function createExecuteTask(contextAuth) {
@@ -152,6 +153,48 @@ function createExecuteTask(contextAuth) {
152
153
  function isRecord(value) {
153
154
  return typeof value === "object" && value !== null;
154
155
  }
156
+ function isBase64BytesPayload(value) {
157
+ if (!isRecord(value)) {
158
+ return false;
159
+ }
160
+ return value.type === "bytes" && value.encoding === "base64" && typeof value.content === "string";
161
+ }
162
+ function decodeBase64BytesPayloads(value) {
163
+ if (isBase64BytesPayload(value)) {
164
+ try {
165
+ return decodeBase64ToUint8Array(value.content);
166
+ } catch {
167
+ return value;
168
+ }
169
+ }
170
+ if (Array.isArray(value)) {
171
+ return value.map((entry) => decodeBase64BytesPayloads(entry));
172
+ }
173
+ if (!isRecord(value)) {
174
+ return value;
175
+ }
176
+ const transformed = {};
177
+ for (const [key, nestedValue] of Object.entries(value)) {
178
+ transformed[key] = decodeBase64BytesPayloads(nestedValue);
179
+ }
180
+ return transformed;
181
+ }
182
+ function decodeBase64ToUint8Array(base64Value) {
183
+ const normalizedBase64 = base64Value.replace(/\s+/g, "");
184
+ if (typeof globalThis.atob === "function") {
185
+ const decoded = globalThis.atob(normalizedBase64);
186
+ const bytes = new Uint8Array(decoded.length);
187
+ for (let index = 0; index < decoded.length; index += 1) {
188
+ bytes[index] = decoded.charCodeAt(index);
189
+ }
190
+ return bytes;
191
+ }
192
+ const globalWithOptionalBuffer = globalThis;
193
+ if (globalWithOptionalBuffer.Buffer) {
194
+ return Uint8Array.from(globalWithOptionalBuffer.Buffer.from(normalizedBase64, "base64"));
195
+ }
196
+ throw new Error("No base64 decoder available in this environment");
197
+ }
155
198
  function isActionExecutePayload(value) {
156
199
  return isRecord(value) && ("result" in value || "success" in value || "error" in value);
157
200
  }
@@ -163,8 +206,29 @@ function toActionExecutionError(payload) {
163
206
  details: payload
164
207
  };
165
208
  }
209
+ function toExecuteTaskSuccess(data) {
210
+ return {
211
+ success: true,
212
+ data
213
+ };
214
+ }
215
+ function toExecuteTaskFailure(error) {
216
+ return {
217
+ success: false,
218
+ data: error
219
+ };
220
+ }
166
221
  function isExecuteTaskError(value) {
167
- return isRecord(value) && typeof value.code === "string" && typeof value.message === "string";
222
+ if (!isRecord(value)) {
223
+ return false;
224
+ }
225
+ if (typeof value.code === "string" && typeof value.message === "string") {
226
+ return true;
227
+ }
228
+ if (value.success !== false || !("data" in value) || !isRecord(value.data)) {
229
+ return false;
230
+ }
231
+ return typeof value.data.code === "string" && typeof value.data.message === "string";
168
232
  }
169
233
 
170
234
  // src/uploadFile.ts
package/dist/index.mjs CHANGED
@@ -55,16 +55,16 @@ async function executeTask(params) {
55
55
  debugApiBaseUrl(baseUrl);
56
56
  try {
57
57
  if (!organizationId) {
58
- return {
58
+ return toExecuteTaskFailure({
59
59
  code: "MISSING_ORGANIZATION_ID",
60
60
  message: "organizationId is required to execute a task"
61
- };
61
+ });
62
62
  }
63
63
  if (!taskId) {
64
- return {
64
+ return toExecuteTaskFailure({
65
65
  code: "MISSING_TASK_ID",
66
66
  message: "taskId is required to execute a task"
67
- };
67
+ });
68
68
  }
69
69
  const headers = {
70
70
  "Content-Type": "application/json"
@@ -85,21 +85,22 @@ async function executeTask(params) {
85
85
  body: JSON.stringify({ inputs })
86
86
  }
87
87
  );
88
- const data = await parseJsonOrText(response);
88
+ const rawData = await parseJsonOrText(response);
89
+ const data = decodeBase64BytesPayloads(rawData);
89
90
  if (!response.ok) {
90
- return toHttpError(response, data);
91
+ return toExecuteTaskFailure(toHttpError(response, data));
91
92
  }
92
93
  if (isActionExecutePayload(data)) {
93
94
  if (data.success === false) {
94
- return toActionExecutionError(data);
95
+ return toExecuteTaskFailure(toActionExecutionError(data));
95
96
  }
96
97
  if ("result" in data) {
97
- return data.result;
98
+ return toExecuteTaskSuccess(data.result);
98
99
  }
99
100
  }
100
- return data ?? void 0;
101
+ return toExecuteTaskSuccess(data ?? void 0);
101
102
  } catch (error) {
102
- return toNetworkError(error);
103
+ return toExecuteTaskFailure(toNetworkError(error));
103
104
  }
104
105
  }
105
106
  function createExecuteTask(contextAuth) {
@@ -117,6 +118,48 @@ function createExecuteTask(contextAuth) {
117
118
  function isRecord(value) {
118
119
  return typeof value === "object" && value !== null;
119
120
  }
121
+ function isBase64BytesPayload(value) {
122
+ if (!isRecord(value)) {
123
+ return false;
124
+ }
125
+ return value.type === "bytes" && value.encoding === "base64" && typeof value.content === "string";
126
+ }
127
+ function decodeBase64BytesPayloads(value) {
128
+ if (isBase64BytesPayload(value)) {
129
+ try {
130
+ return decodeBase64ToUint8Array(value.content);
131
+ } catch {
132
+ return value;
133
+ }
134
+ }
135
+ if (Array.isArray(value)) {
136
+ return value.map((entry) => decodeBase64BytesPayloads(entry));
137
+ }
138
+ if (!isRecord(value)) {
139
+ return value;
140
+ }
141
+ const transformed = {};
142
+ for (const [key, nestedValue] of Object.entries(value)) {
143
+ transformed[key] = decodeBase64BytesPayloads(nestedValue);
144
+ }
145
+ return transformed;
146
+ }
147
+ function decodeBase64ToUint8Array(base64Value) {
148
+ const normalizedBase64 = base64Value.replace(/\s+/g, "");
149
+ if (typeof globalThis.atob === "function") {
150
+ const decoded = globalThis.atob(normalizedBase64);
151
+ const bytes = new Uint8Array(decoded.length);
152
+ for (let index = 0; index < decoded.length; index += 1) {
153
+ bytes[index] = decoded.charCodeAt(index);
154
+ }
155
+ return bytes;
156
+ }
157
+ const globalWithOptionalBuffer = globalThis;
158
+ if (globalWithOptionalBuffer.Buffer) {
159
+ return Uint8Array.from(globalWithOptionalBuffer.Buffer.from(normalizedBase64, "base64"));
160
+ }
161
+ throw new Error("No base64 decoder available in this environment");
162
+ }
120
163
  function isActionExecutePayload(value) {
121
164
  return isRecord(value) && ("result" in value || "success" in value || "error" in value);
122
165
  }
@@ -128,8 +171,29 @@ function toActionExecutionError(payload) {
128
171
  details: payload
129
172
  };
130
173
  }
174
+ function toExecuteTaskSuccess(data) {
175
+ return {
176
+ success: true,
177
+ data
178
+ };
179
+ }
180
+ function toExecuteTaskFailure(error) {
181
+ return {
182
+ success: false,
183
+ data: error
184
+ };
185
+ }
131
186
  function isExecuteTaskError(value) {
132
- return isRecord(value) && typeof value.code === "string" && typeof value.message === "string";
187
+ if (!isRecord(value)) {
188
+ return false;
189
+ }
190
+ if (typeof value.code === "string" && typeof value.message === "string") {
191
+ return true;
192
+ }
193
+ if (value.success !== false || !("data" in value) || !isRecord(value.data)) {
194
+ return false;
195
+ }
196
+ return typeof value.data.code === "string" && typeof value.data.message === "string";
133
197
  }
134
198
 
135
199
  // src/uploadFile.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brixel_ai/artifact-sdk",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "SDK for building Brixel Artifacts - interactive React components that integrate with Brixel workflows",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",