@elaraai/e3-ui-components 0.0.1-beta.16 → 0.0.1-beta.17

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.
@@ -1 +1 @@
1
- {"version":3,"file":"InputPreview.d.ts","sourceRoot":"","sources":["../../src/components/InputPreview.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AA2BH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAO7D,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,yDA+KuD,CAAC"}
1
+ {"version":3,"file":"InputPreview.d.ts","sourceRoot":"","sources":["../../src/components/InputPreview.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AA2BH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAO7D,MAAM,WAAW,iBAAiB;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,yDAuLuD,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { RequestOptions } from '@elaraai/e3-api-client';
2
+ export interface TaskLogsProps {
3
+ apiUrl: string;
4
+ repo: string;
5
+ workspace: string;
6
+ task: string;
7
+ requestOptions?: RequestOptions;
8
+ }
9
+ /**
10
+ * Renders a virtualized log viewer for a task's stdout/stderr.
11
+ */
12
+ export declare const TaskLogs: import('react').NamedExoticComponent<TaskLogsProps>;
13
+ //# sourceMappingURL=TaskLogs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskLogs.d.ts","sourceRoot":"","sources":["../../src/components/TaskLogs.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,MAAM,WAAW,aAAa;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAED;;GAEG;AACH,eAAO,MAAM,QAAQ,qDA4BnB,CAAC"}
@@ -9,8 +9,7 @@ export interface TaskPreviewProps {
9
9
  }
10
10
  /**
11
11
  * Renders a preview of a task's output and logs.
12
- * Decodes Beast2 data and renders as an East UI component if possible,
13
- * with a virtualized log viewer for stdout/stderr.
12
+ * Composes TaskUI/TaskValue for output and TaskLogs for stdout/stderr.
14
13
  */
15
14
  export declare const TaskPreview: import('react').NamedExoticComponent<TaskPreviewProps>;
16
15
  //# sourceMappingURL=TaskPreview.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TaskPreview.d.ts","sourceRoot":"","sources":["../../src/components/TaskPreview.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAiCH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAO7D,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAED;;;;GAIG;AACH,eAAO,MAAM,WAAW,wDA6NkH,CAAC"}
1
+ {"version":3,"file":"TaskPreview.d.ts","sourceRoot":"","sources":["../../src/components/TaskPreview.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAI7D,MAAM,WAAW,gBAAgB;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,wDAsEkH,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { RequestOptions } from '@elaraai/e3-api-client';
2
+ export interface TaskUIProps {
3
+ apiUrl: string;
4
+ repo: string;
5
+ workspace: string;
6
+ task: string;
7
+ output: string;
8
+ requestOptions?: RequestOptions;
9
+ }
10
+ /**
11
+ * Renders a task's output as an East UI component.
12
+ * Decodes Beast2 data and renders it using EastChakraComponent.
13
+ */
14
+ export declare const TaskUI: import('react').NamedExoticComponent<TaskUIProps>;
15
+ //# sourceMappingURL=TaskUI.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskUI.d.ts","sourceRoot":"","sources":["../../src/components/TaskUI.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAsBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAI7D,MAAM,WAAW,WAAW;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAUD;;;GAGG;AACH,eAAO,MAAM,MAAM,mDAqHjB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { RequestOptions } from '@elaraai/e3-api-client';
2
+ export interface TaskValueProps {
3
+ apiUrl: string;
4
+ repo: string;
5
+ workspace: string;
6
+ task: string;
7
+ output: string;
8
+ requestOptions?: RequestOptions;
9
+ }
10
+ /**
11
+ * Renders a preview of a task's non-UI output value.
12
+ * Decodes Beast2 data and displays it using EastValueViewer.
13
+ */
14
+ export declare const TaskValue: import('react').NamedExoticComponent<TaskValueProps>;
15
+ //# sourceMappingURL=TaskValue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskValue.d.ts","sourceRoot":"","sources":["../../src/components/TaskValue.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAUH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAW7D,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,cAAc,CAAC;CACnC;AAUD;;;GAGG;AACH,eAAO,MAAM,SAAS,sDAwEpB,CAAC"}
@@ -4,6 +4,9 @@
4
4
  */
5
5
  export { InputPreview, type InputPreviewProps } from './InputPreview.js';
6
6
  export { TaskPreview, type TaskPreviewProps } from './TaskPreview.js';
7
+ export { TaskLogs, type TaskLogsProps } from './TaskLogs.js';
8
+ export { TaskUI, type TaskUIProps } from './TaskUI.js';
9
+ export { TaskValue, type TaskValueProps } from './TaskValue.js';
7
10
  export { StatusDisplay, type StatusDisplayProps } from './StatusDisplay.js';
8
11
  export { EastValueViewer, type EastValueViewerProps } from './EastValueViewer.js';
9
12
  export { VirtualizedLogViewer, type VirtualizedLogViewerProps } from './VirtualizedLogViewer.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,KAAK,yBAAyB,EAAE,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,KAAK,yBAAyB,EAAE,MAAM,2BAA2B,CAAC"}
package/dist/index.cjs CHANGED
@@ -4861,7 +4861,7 @@ function EastValueViewer({ type, value }) {
4861
4861
  }
4862
4862
  );
4863
4863
  }
4864
- const platformImplementations$1 = [...eastUiComponents.StateImpl, ...eastUiComponents.DatasetImpl, ...eastUiComponents.OverlayImpl];
4864
+ const platformImplementations$2 = [...eastUiComponents.StateImpl, ...eastUiComponents.DatasetImpl, ...eastUiComponents.OverlayImpl];
4865
4865
  const InputPreview = React.memo(function InputPreview2({
4866
4866
  apiUrl,
4867
4867
  repo,
@@ -4874,21 +4874,27 @@ const InputPreview = React.memo(function InputPreview2({
4874
4874
  () => (preview == null ? void 0 : preview.value.type) === "some" ? preview.value.value : void 0,
4875
4875
  [preview]
4876
4876
  );
4877
+ const isUIComponent = React.useMemo(() => {
4878
+ if (!preview) return false;
4879
+ try {
4880
+ return east.isTypeValueEqual(preview.type, east.toEastTypeValue(eastUi.UIComponentType));
4881
+ } catch {
4882
+ return false;
4883
+ }
4884
+ }, [preview]);
4877
4885
  const decode = React.useMemo(() => {
4878
4886
  if (!output) return { type: "none" };
4887
+ if (!isUIComponent) return { type: "other" };
4879
4888
  try {
4880
- const { type } = east.decodeBeast2(output);
4881
- if (!east.isTypeValueEqual(type, east.toEastTypeValue(eastUi.UIComponentType))) return { type: "other" };
4882
- try {
4883
- const decoder = east.decodeBeast2For(eastUi.UIComponentType, { platform: platformImplementations$1 });
4884
- return { type: "ui", value: decoder(output) };
4885
- } catch (e2) {
4886
- return { type: "ui-error", error: e2 instanceof Error ? e2 : new Error(String(e2)) };
4887
- }
4888
- } catch {
4889
- return { type: "other" };
4889
+ const decoder = east.decodeBeast2For(eastUi.UIComponentType, {
4890
+ platform: platformImplementations$2,
4891
+ skipTypeCheck: true
4892
+ });
4893
+ return { type: "ui", value: decoder(output) };
4894
+ } catch (e2) {
4895
+ return { type: "ui-error", error: e2 instanceof Error ? e2 : new Error(String(e2)) };
4890
4896
  }
4891
- }, [output]);
4897
+ }, [output, isUIComponent]);
4892
4898
  const store = React.useMemo(() => eastUiComponents.createEastStore(), [decode]);
4893
4899
  const displayName = path.replace(/^\.inputs\./, "");
4894
4900
  const hasData = React.useMemo(() => {
@@ -5357,55 +5363,6 @@ function VirtualizedLogViewer({ content, tabs }) {
5357
5363
  }
5358
5364
  );
5359
5365
  }
5360
- const MAX_DOWNLOAD_SIZE = 50 * 1024 * 1024;
5361
- function useTaskOutputPreview(apiUrl, repo, workspace, outputPath, requestOptions, queryOptions) {
5362
- const pathParts = React.useMemo(
5363
- () => (outputPath == null ? void 0 : outputPath.split(".").map((v2) => east.variant("field", v2))) ?? [],
5364
- [outputPath]
5365
- );
5366
- const status = reactQuery.useQuery({
5367
- queryKey: ["taskOutputStatus", apiUrl, repo, workspace, outputPath],
5368
- queryFn: () => e3ApiClient.datasetGetStatus(apiUrl, repo, workspace, pathParts, requestOptions ?? { token: null }),
5369
- enabled: !!workspace && !!outputPath,
5370
- refetchInterval: 1e3,
5371
- ...queryOptions
5372
- });
5373
- const hash = React.useMemo(() => {
5374
- var _a, _b;
5375
- return ((_b = (_a = status.data) == null ? void 0 : _a.hash) == null ? void 0 : _b.type) === "some" ? status.data.hash.value : null;
5376
- }, [status.data]);
5377
- const hasData = React.useMemo(() => {
5378
- var _a;
5379
- return ((_a = status.data) == null ? void 0 : _a.refType) === "value" && hash !== null;
5380
- }, [status.data, hash]);
5381
- const size = React.useMemo(() => {
5382
- var _a, _b;
5383
- return ((_b = (_a = status.data) == null ? void 0 : _a.size) == null ? void 0 : _b.type) === "some" ? status.data.size.value : null;
5384
- }, [status.data]);
5385
- const isOversized = React.useMemo(() => size !== null && size > MAX_DOWNLOAD_SIZE, [size]);
5386
- const data = reactQuery.useQuery({
5387
- queryKey: ["taskOutput", apiUrl, repo, workspace, outputPath, hash],
5388
- queryFn: () => e3ApiClient.datasetGet(apiUrl, repo, workspace, pathParts, requestOptions ?? { token: null }),
5389
- enabled: hasData && !isOversized,
5390
- ...queryOptions
5391
- });
5392
- const preview = React.useMemo(() => {
5393
- if (!status.data) return void 0;
5394
- return {
5395
- path: status.data.path,
5396
- type: status.data.type,
5397
- refType: status.data.refType,
5398
- hash: status.data.hash,
5399
- size: status.data.size,
5400
- value: data.data ? east.some(data.data.data) : east.none
5401
- };
5402
- }, [status.data, data.data]);
5403
- return {
5404
- data: preview,
5405
- isLoading: status.isLoading || status.isSuccess && hasData && !isOversized && data.isLoading,
5406
- error: status.error ?? data.error ?? null
5407
- };
5408
- }
5409
5366
  const CHUNK_SIZE = 64 * 1024;
5410
5367
  const MAX_TOTAL_SIZE = 10 * 1024 * 1024;
5411
5368
  async function fetchAllLogs(apiUrl, repo, workspace, taskName, stream, requestOptions) {
@@ -5452,138 +5409,254 @@ function useTaskLogs(apiUrl, repo, workspace, taskName, stream = "stdout", reque
5452
5409
  ...queryOptions
5453
5410
  });
5454
5411
  }
5455
- const platformImplementations = [...eastUiComponents.StateImpl, ...eastUiComponents.DatasetImpl, ...eastUiComponents.OverlayImpl];
5456
- const TaskPreview = React.memo(function TaskPreview2({
5412
+ const TaskLogs = React.memo(function TaskLogs2({
5457
5413
  apiUrl,
5458
5414
  repo,
5459
5415
  workspace,
5460
5416
  task,
5461
- output,
5462
5417
  requestOptions
5463
5418
  }) {
5464
- const { data: preview, isLoading, error } = useTaskOutputPreview(apiUrl, repo, workspace, output, requestOptions);
5465
- const rawOutput = React.useMemo(
5466
- () => (preview == null ? void 0 : preview.value.type) === "some" ? preview.value.value : void 0,
5467
- [preview]
5468
- );
5469
5419
  const { data: stdout } = useTaskLogs(apiUrl, repo, workspace, task, "stdout", requestOptions);
5470
5420
  const { data: stderr } = useTaskLogs(apiUrl, repo, workspace, task, "stderr", requestOptions);
5471
- const ir = React.useMemo(() => {
5472
- if (!rawOutput) return null;
5473
- try {
5474
- const { type } = east.decodeBeast2(rawOutput);
5475
- if (east.isTypeValueEqual(type, east.toEastTypeValue(eastUi.UIComponentType))) {
5476
- const decoder = east.decodeBeast2For(eastUi.UIComponentType, { platform: platformImplementations });
5477
- const value = decoder(rawOutput);
5478
- return value;
5479
- } else {
5480
- return null;
5481
- }
5482
- } catch {
5483
- return null;
5484
- }
5485
- }, [rawOutput]);
5486
- const store = React.useMemo(() => eastUiComponents.createEastStore(), [ir]);
5487
5421
  const stdoutContent = React.useMemo(() => (stdout == null ? void 0 : stdout.data) ?? "", [stdout == null ? void 0 : stdout.data]);
5488
5422
  const stderrContent = React.useMemo(() => (stderr == null ? void 0 : stderr.data) ?? "", [stderr == null ? void 0 : stderr.data]);
5489
5423
  const tabs = react.useTabs({
5490
5424
  defaultValue: "stdout"
5491
5425
  });
5492
- const [viewMode, setViewMode] = React.useState(null);
5493
- React.useEffect(() => {
5494
- if (isLoading) return;
5495
- setViewMode((prev) => {
5496
- if (prev !== null) return prev;
5497
- return ir === null ? "logs" : "output";
5498
- });
5499
- }, [isLoading, ir]);
5426
+ const activeLogContent = React.useMemo(
5427
+ () => tabs.value === "stderr" ? stderrContent : stdoutContent,
5428
+ [tabs.value, stderrContent, stdoutContent]
5429
+ );
5430
+ return /* @__PURE__ */ jsxRuntime.jsx(
5431
+ VirtualizedLogViewer,
5432
+ {
5433
+ content: activeLogContent,
5434
+ tabs
5435
+ }
5436
+ );
5437
+ });
5438
+ const MAX_DOWNLOAD_SIZE = 50 * 1024 * 1024;
5439
+ function useTaskOutputPreview(apiUrl, repo, workspace, outputPath, requestOptions, queryOptions) {
5440
+ const pathParts = React.useMemo(
5441
+ () => (outputPath == null ? void 0 : outputPath.split(".").map((v2) => east.variant("field", v2))) ?? [],
5442
+ [outputPath]
5443
+ );
5444
+ const status = reactQuery.useQuery({
5445
+ queryKey: ["taskOutputStatus", apiUrl, repo, workspace, outputPath],
5446
+ queryFn: () => e3ApiClient.datasetGetStatus(apiUrl, repo, workspace, pathParts, requestOptions ?? { token: null }),
5447
+ enabled: !!workspace && !!outputPath,
5448
+ refetchInterval: 1e3,
5449
+ ...queryOptions
5450
+ });
5451
+ const hash = React.useMemo(() => {
5452
+ var _a, _b;
5453
+ return ((_b = (_a = status.data) == null ? void 0 : _a.hash) == null ? void 0 : _b.type) === "some" ? status.data.hash.value : null;
5454
+ }, [status.data]);
5500
5455
  const hasData = React.useMemo(() => {
5501
5456
  var _a;
5502
- return (preview == null ? void 0 : preview.refType) === "value" && ((_a = preview == null ? void 0 : preview.hash) == null ? void 0 : _a.type) === "some";
5503
- }, [preview]);
5504
- const outputPanel = React.useMemo(() => {
5505
- if (preview && !hasData) {
5506
- return /* @__PURE__ */ jsxRuntime.jsx(
5507
- StatusDisplay,
5508
- {
5509
- variant: "info",
5510
- title: "No output available",
5511
- message: "Run the task to see output"
5512
- }
5513
- );
5514
- }
5515
- if (isLoading) {
5516
- return /* @__PURE__ */ jsxRuntime.jsx(
5517
- StatusDisplay,
5518
- {
5519
- variant: "loading",
5520
- title: "Loading output..."
5521
- }
5522
- );
5457
+ return ((_a = status.data) == null ? void 0 : _a.refType) === "value" && hash !== null;
5458
+ }, [status.data, hash]);
5459
+ const size = React.useMemo(() => {
5460
+ var _a, _b;
5461
+ return ((_b = (_a = status.data) == null ? void 0 : _a.size) == null ? void 0 : _b.type) === "some" ? status.data.size.value : null;
5462
+ }, [status.data]);
5463
+ const isOversized = React.useMemo(() => size !== null && size > MAX_DOWNLOAD_SIZE, [size]);
5464
+ const data = reactQuery.useQuery({
5465
+ queryKey: ["taskOutput", apiUrl, repo, workspace, outputPath, hash],
5466
+ queryFn: () => e3ApiClient.datasetGet(apiUrl, repo, workspace, pathParts, requestOptions ?? { token: null }),
5467
+ enabled: hasData && !isOversized,
5468
+ ...queryOptions
5469
+ });
5470
+ const preview = React.useMemo(() => {
5471
+ if (!status.data) return void 0;
5472
+ return {
5473
+ path: status.data.path,
5474
+ type: status.data.type,
5475
+ refType: status.data.refType,
5476
+ hash: status.data.hash,
5477
+ size: status.data.size,
5478
+ value: data.data ? east.some(data.data.data) : east.none
5479
+ };
5480
+ }, [status.data, data.data]);
5481
+ return {
5482
+ data: preview,
5483
+ isLoading: status.isLoading || status.isSuccess && hasData && !isOversized && data.isLoading,
5484
+ error: status.error ?? data.error ?? null
5485
+ };
5486
+ }
5487
+ const platformImplementations$1 = [...eastUiComponents.StateImpl, ...eastUiComponents.DatasetImpl, ...eastUiComponents.OverlayImpl];
5488
+ const TaskValue = React.memo(function TaskValue2({
5489
+ apiUrl,
5490
+ repo,
5491
+ workspace,
5492
+ output,
5493
+ requestOptions
5494
+ }) {
5495
+ const { data: preview, isLoading, error } = useTaskOutputPreview(apiUrl, repo, workspace, output, requestOptions);
5496
+ const previewState = React.useMemo(() => {
5497
+ var _a;
5498
+ if (!preview || isLoading) return { status: "loading" };
5499
+ const hasData = preview.refType === "value" && ((_a = preview.hash) == null ? void 0 : _a.type) === "some";
5500
+ if (!hasData) return { status: "no-data" };
5501
+ if (preview.value.type === "none") {
5502
+ return {
5503
+ status: "oversized",
5504
+ sizeBytes: Number(preview.size.type === "some" ? preview.size.value : 0)
5505
+ };
5523
5506
  }
5524
- if (!preview) {
5525
- return /* @__PURE__ */ jsxRuntime.jsx(
5526
- StatusDisplay,
5527
- {
5528
- variant: "info",
5529
- title: `No output available for task "${task}"`
5530
- }
5531
- );
5507
+ const rawOutput = preview.value.value;
5508
+ let decoder;
5509
+ try {
5510
+ decoder = east.decodeBeast2For(preview.type, {
5511
+ platform: platformImplementations$1,
5512
+ skipTypeCheck: true
5513
+ });
5514
+ } catch (e2) {
5515
+ return {
5516
+ status: "decode-error",
5517
+ error: e2 instanceof Error ? e2.message : String(e2)
5518
+ };
5532
5519
  }
5533
- if (preview.value.type === "none") {
5534
- const sizeBytes = Number(preview.size.type === "some" ? preview.size.value : 0);
5520
+ return { status: "value", rawOutput, decoder };
5521
+ }, [preview, isLoading]);
5522
+ if (error) {
5523
+ return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Failed to load task output", details: error instanceof Error ? error.message : String(error) });
5524
+ }
5525
+ switch (previewState.status) {
5526
+ case "loading":
5527
+ return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "loading", title: "Loading output..." });
5528
+ case "no-data":
5529
+ return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "info", title: "No output available", message: "Run the task to see output" });
5530
+ case "oversized":
5535
5531
  return /* @__PURE__ */ jsxRuntime.jsx(
5536
5532
  StatusDisplay,
5537
5533
  {
5538
5534
  variant: "warning",
5539
5535
  title: "Output too large to display",
5540
- message: `The task output is ${(sizeBytes / 1024 / 1024).toFixed(2)} MB, which exceeds the 10 MB display limit.`
5536
+ message: `The task output is ${(previewState.sizeBytes / 1024 / 1024).toFixed(2)} MB, which exceeds the 10 MB display limit.`
5541
5537
  }
5542
5538
  );
5543
- }
5544
- if (ir !== null) {
5545
- return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { height: "100%", overflow: "auto", p: "4", children: /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.EastChakraComponent, { value: ir }) });
5546
- }
5547
- if (rawOutput && ir === null) {
5539
+ case "decode-error":
5540
+ return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Failed to render output", details: previewState.error });
5541
+ case "value":
5548
5542
  try {
5549
- const decoded = east.decodeBeast2(rawOutput);
5543
+ const decoded = previewState.decoder(previewState.rawOutput);
5550
5544
  return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { height: "100%", overflow: "auto", p: "4", children: /* @__PURE__ */ jsxRuntime.jsx(EastValueViewer, { type: decoded.type, value: decoded.value }) });
5551
5545
  } catch (e2) {
5552
5546
  const errorMessage = e2 instanceof Error ? e2.message : String(e2);
5553
5547
  return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Failed to render output", details: errorMessage });
5554
5548
  }
5555
- }
5556
- return /* @__PURE__ */ jsxRuntime.jsx(
5557
- StatusDisplay,
5558
- {
5559
- variant: "info",
5560
- title: `No output available for task "${task}"`
5561
- }
5562
- );
5563
- }, [preview, ir, task, isLoading, rawOutput, hasData]);
5564
- const activeLogContent = React.useMemo(() => tabs.value === "stderr" ? stderrContent : stdoutContent, [tabs.value, stderrContent, stdoutContent]);
5565
- const logsPanel = React.useMemo(() => {
5566
- return /* @__PURE__ */ jsxRuntime.jsx(
5567
- VirtualizedLogViewer,
5568
- {
5569
- content: activeLogContent,
5570
- tabs
5571
- }
5572
- );
5573
- }, [activeLogContent, tabs]);
5574
- if (viewMode === null) {
5575
- return /* @__PURE__ */ jsxRuntime.jsx(
5576
- StatusDisplay,
5577
- {
5578
- variant: "loading",
5579
- title: "Loading task..."
5580
- }
5581
- );
5582
5549
  }
5550
+ });
5551
+ const platformImplementations = [...eastUiComponents.StateImpl, ...eastUiComponents.DatasetImpl, ...eastUiComponents.OverlayImpl];
5552
+ const TaskUI = React.memo(function TaskUI2({
5553
+ apiUrl,
5554
+ repo,
5555
+ workspace,
5556
+ task,
5557
+ output,
5558
+ requestOptions
5559
+ }) {
5560
+ const { data: preview, isLoading, error } = useTaskOutputPreview(apiUrl, repo, workspace, output, requestOptions);
5561
+ const previewState = React.useMemo(() => {
5562
+ var _a;
5563
+ if (!preview || isLoading) return { status: "loading" };
5564
+ const hasData = preview.refType === "value" && ((_a = preview.hash) == null ? void 0 : _a.type) === "some";
5565
+ if (!hasData) return { status: "no-data" };
5566
+ if (preview.value.type === "none") {
5567
+ return {
5568
+ status: "oversized",
5569
+ sizeBytes: Number(preview.size.type === "some" ? preview.size.value : 0)
5570
+ };
5571
+ }
5572
+ const rawOutput = preview.value.value;
5573
+ const totalStart = performance.now();
5574
+ let decoder;
5575
+ try {
5576
+ decoder = east.decodeBeast2For(preview.type, {
5577
+ platform: platformImplementations,
5578
+ skipTypeCheck: true
5579
+ });
5580
+ } catch (e2) {
5581
+ return {
5582
+ status: "decode-error",
5583
+ error: e2 instanceof Error ? e2.message : String(e2)
5584
+ };
5585
+ }
5586
+ const buildDecoderMs = performance.now() - totalStart;
5587
+ let isUI = false;
5588
+ try {
5589
+ isUI = east.isTypeValueEqual(preview.type, east.toEastTypeValue(eastUi.UIComponentType));
5590
+ } catch {
5591
+ }
5592
+ if (!isUI) {
5593
+ return { status: "not-ui" };
5594
+ }
5595
+ try {
5596
+ const decodeStart = performance.now();
5597
+ const ir = decoder(rawOutput);
5598
+ const decodeMs = performance.now() - decodeStart;
5599
+ const totalMs = performance.now() - totalStart;
5600
+ console.log(`[east-ui] decodeBeast2 total: ${totalMs.toFixed(1)}ms`);
5601
+ console.log(` buildDecoder: ${buildDecoderMs.toFixed(1)}ms, decode: ${decodeMs.toFixed(1)}ms`);
5602
+ console.log(` payload size: ${(rawOutput.length / 1024).toFixed(1)} KB`);
5603
+ return { status: "ui", ir };
5604
+ } catch (e2) {
5605
+ return {
5606
+ status: "decode-error",
5607
+ error: e2 instanceof Error ? e2.message : String(e2)
5608
+ };
5609
+ }
5610
+ }, [preview, isLoading]);
5611
+ const store = React.useMemo(() => eastUiComponents.createEastStore(), []);
5583
5612
  if (error) {
5584
5613
  return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Failed to load task output", details: error instanceof Error ? error.message : String(error) });
5585
5614
  }
5586
- return /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.EastStoreProvider, { store, children: /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { height: "100%", display: "flex", flexDirection: "column", overflow: "hidden", children: [
5615
+ const content = (() => {
5616
+ switch (previewState.status) {
5617
+ case "loading":
5618
+ return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "loading", title: "Loading output..." });
5619
+ case "no-data":
5620
+ return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "info", title: "No output available", message: "Run the task to see output" });
5621
+ case "oversized":
5622
+ return /* @__PURE__ */ jsxRuntime.jsx(
5623
+ StatusDisplay,
5624
+ {
5625
+ variant: "warning",
5626
+ title: "Output too large to display",
5627
+ message: `The task output is ${(previewState.sizeBytes / 1024 / 1024).toFixed(2)} MB, which exceeds the 10 MB display limit.`
5628
+ }
5629
+ );
5630
+ case "ui":
5631
+ return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { height: "100%", overflow: "auto", p: "4", children: /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.EastChakraComponent, { value: previewState.ir }) });
5632
+ case "not-ui":
5633
+ return /* @__PURE__ */ jsxRuntime.jsx(
5634
+ TaskValue,
5635
+ {
5636
+ apiUrl,
5637
+ repo,
5638
+ workspace,
5639
+ task,
5640
+ output,
5641
+ ...requestOptions != null && { requestOptions }
5642
+ }
5643
+ );
5644
+ case "decode-error":
5645
+ return /* @__PURE__ */ jsxRuntime.jsx(StatusDisplay, { variant: "error", title: "Failed to render output", details: previewState.error });
5646
+ }
5647
+ })();
5648
+ return /* @__PURE__ */ jsxRuntime.jsx(eastUiComponents.EastStoreProvider, { store, children: content });
5649
+ });
5650
+ const TaskPreview = React.memo(function TaskPreview2({
5651
+ apiUrl,
5652
+ repo,
5653
+ workspace,
5654
+ task,
5655
+ output,
5656
+ requestOptions
5657
+ }) {
5658
+ const [viewMode, setViewMode] = React.useState("output");
5659
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { height: "100%", display: "flex", flexDirection: "column", overflow: "hidden", children: [
5587
5660
  /* @__PURE__ */ jsxRuntime.jsxs(
5588
5661
  react.Flex,
5589
5662
  {
@@ -5619,8 +5692,27 @@ const TaskPreview = React.memo(function TaskPreview2({
5619
5692
  ]
5620
5693
  }
5621
5694
  ),
5622
- /* @__PURE__ */ jsxRuntime.jsx(react.Box, { flex: 1, overflow: "hidden", minHeight: 0, children: viewMode === "output" ? outputPanel : logsPanel })
5623
- ] }) });
5695
+ /* @__PURE__ */ jsxRuntime.jsx(react.Box, { flex: 1, overflow: "hidden", minHeight: 0, children: viewMode === "output" ? /* @__PURE__ */ jsxRuntime.jsx(
5696
+ TaskUI,
5697
+ {
5698
+ apiUrl,
5699
+ repo,
5700
+ workspace,
5701
+ task,
5702
+ output,
5703
+ ...requestOptions != null && { requestOptions }
5704
+ }
5705
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
5706
+ TaskLogs,
5707
+ {
5708
+ apiUrl,
5709
+ repo,
5710
+ workspace,
5711
+ task,
5712
+ ...requestOptions != null && { requestOptions }
5713
+ }
5714
+ ) })
5715
+ ] });
5624
5716
  }, (prev, next) => prev.task === next.task && prev.repo === next.repo && prev.workspace === next.workspace && prev.output === next.output);
5625
5717
  exports.EastValueViewer = EastValueViewer;
5626
5718
  exports.ErrorBoundary = ErrorBoundary;