@agimon-ai/po-workflow 0.0.0-alpha.34 → 0.0.0-alpha.36

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,6 +1,6 @@
1
- import { createApiClient, defineActivityGroup, defineChannelFile, defineFill, defineNativePlugin, defineSessionStore, nativeApiTransport, sessionApiAddress } from "@agimon-ai/po-core/native";
1
+ import { createApiClient, defineActivityGroup, defineChannelFile, defineFill, defineNativePlugin, defineSessionStore, encodeBase64, nativeApiTransport, sessionApiAddress } from "@agimon-ai/po-core/native";
2
2
  import { ArrowRightIcon, Badge, Button, CodeBlock, Dot, Input, ListRow, Markdown, Sheet, SheetBody, SheetContent, SheetHeader, SheetTitle, Textarea, WorkflowIcon, fontOf } from "@agimon-ai/po-native-components";
3
- import { createElement, useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
3
+ import { createElement, memo, useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
4
  import { View } from "react-native-unistyles/components/native/View";
5
5
  import { Text } from "react-native-unistyles/components/native/Text";
6
6
  import { ScrollView } from "react-native-unistyles/components/native/ScrollView";
@@ -475,7 +475,7 @@ function finiteScreenReader(load) {
475
475
  const chunk = bytes.subarray(cursor, cursor + MAX_FRAME_BYTES);
476
476
  cursor += chunk.length;
477
477
  return {
478
- chunk: base64(chunk),
478
+ chunk: encodeBase64(chunk),
479
479
  offset: cursor,
480
480
  reset,
481
481
  generation: String(generation),
@@ -498,27 +498,10 @@ async function fetchArtifactMedia(workspace, runKey, path, sessionId, signal) {
498
498
  if (signal.aborted) throw new Error("Preview cancelled.");
499
499
  if (bytes.byteLength > MAX_MEDIA_BYTES) throw new Error("This artifact exceeds the 5 MiB preview limit.");
500
500
  return {
501
- data: base64(new Uint8Array(bytes)),
501
+ data: encodeBase64(new Uint8Array(bytes)),
502
502
  mimeType
503
503
  };
504
504
  }
505
- function base64(bytes) {
506
- const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
507
- const parts = [];
508
- let chunk = "";
509
- for (let offset = 0; offset < bytes.length; offset += 3) {
510
- const first = bytes[offset];
511
- const second = bytes[offset + 1];
512
- const third = bytes[offset + 2];
513
- chunk += alphabet[first >> 2] + alphabet[(first & 3) << 4 | (second ?? 0) >> 4] + (second === void 0 ? "=" : alphabet[(second & 15) << 2 | (third ?? 0) >> 6]) + (third === void 0 ? "=" : alphabet[third & 63]);
514
- if (chunk.length >= 8192) {
515
- parts.push(chunk);
516
- chunk = "";
517
- }
518
- }
519
- parts.push(chunk);
520
- return parts.join("");
521
- }
522
505
  function utf8(text) {
523
506
  const bytes = [];
524
507
  for (const character of text) {
@@ -724,6 +707,209 @@ const workflowRunsChannel = workflows.channel({
724
707
  }
725
708
  });
726
709
  //#endregion
710
+ //#region src/extensions/workspaces/sessions/(frontend)/_lib/delimitedPreview.ts
711
+ /** Index record boundaries and widths without allocating hidden cell strings. */
712
+ function indexDelimited(text, delimiter) {
713
+ const rowStarts = text.length === 0 ? [] : [0];
714
+ let columns = text.length === 0 ? 0 : 1;
715
+ let width = columns;
716
+ let quoted = false;
717
+ let atCellStart = true;
718
+ for (let index = 0; index < text.length; index += 1) {
719
+ const character = text[index];
720
+ if (quoted) {
721
+ if (character === "\"" && text[index + 1] === "\"") index += 1;
722
+ else if (character === "\"") quoted = false;
723
+ } else if (character === "\"" && atCellStart) {
724
+ quoted = true;
725
+ atCellStart = false;
726
+ } else if (character === delimiter) {
727
+ width += 1;
728
+ atCellStart = true;
729
+ } else if (character === "\n" || character === "\r") {
730
+ columns = Math.max(columns, width);
731
+ width = 1;
732
+ atCellStart = true;
733
+ if (character === "\r" && text[index + 1] === "\n") index += 1;
734
+ if (index + 1 < text.length) rowStarts.push(index + 1);
735
+ } else atCellStart = false;
736
+ }
737
+ return {
738
+ rowStarts,
739
+ columns: Math.max(columns, width)
740
+ };
741
+ }
742
+ /** Decode only requested records and columns. Every source record remains indexed. */
743
+ function readDelimitedWindow(text, delimiter, document, rowLimit, columnLimit) {
744
+ return document.rowStarts.slice(0, rowLimit).map((start) => {
745
+ const cells = [];
746
+ let cell = "";
747
+ let quoted = false;
748
+ let atCellStart = true;
749
+ for (let index = start; index < text.length; index += 1) {
750
+ const character = text[index];
751
+ if (quoted) {
752
+ if (character === "\"" && text[index + 1] === "\"") {
753
+ cell += "\"";
754
+ index += 1;
755
+ } else if (character === "\"") quoted = false;
756
+ else cell += character;
757
+ } else if (character === "\"" && atCellStart) {
758
+ quoted = true;
759
+ atCellStart = false;
760
+ } else if (character === delimiter) {
761
+ cells.push(cell);
762
+ if (cells.length === columnLimit) return cells;
763
+ cell = "";
764
+ atCellStart = true;
765
+ } else if (character === "\n" || character === "\r") break;
766
+ else {
767
+ cell += character;
768
+ atCellStart = false;
769
+ }
770
+ }
771
+ if (cells.length < columnLimit) cells.push(cell);
772
+ return cells;
773
+ });
774
+ }
775
+ //#endregion
776
+ //#region src/extensions/workspaces/sessions/(frontend)/_components/DelimitedArtifact.native.tsx
777
+ /** Pure CSV/TSV preview shared with its design target. Labels never consume a source record. */
778
+ const DelimitedArtifact = memo(function DelimitedArtifact({ text, delimiter, initialRows = 20 }) {
779
+ const document = useMemo(() => indexDelimited(text, delimiter), [text, delimiter]);
780
+ const [window, setWindow] = useState({
781
+ document,
782
+ rows: initialRows,
783
+ columns: 8
784
+ });
785
+ const current = window.document === document ? window : {
786
+ document,
787
+ rows: initialRows,
788
+ columns: 8
789
+ };
790
+ if (current !== window) setWindow(current);
791
+ const rowCount = document.rowStarts.length;
792
+ const rows = Math.min(rowCount, current.rows);
793
+ const columns = Math.min(document.columns, current.columns);
794
+ const cells = useMemo(() => readDelimitedWindow(text, delimiter, document, rows, columns), [
795
+ text,
796
+ delimiter,
797
+ document,
798
+ rows,
799
+ columns
800
+ ]);
801
+ return /* @__PURE__ */ jsxs(View, {
802
+ style: styles$2.body,
803
+ children: [
804
+ /* @__PURE__ */ jsxs(Text, {
805
+ style: styles$2.meta,
806
+ accessibilityLiveRegion: "polite",
807
+ children: [
808
+ "Rows ",
809
+ rows === 0 ? 0 : 1,
810
+ "–",
811
+ rows,
812
+ " of ",
813
+ rowCount,
814
+ " · Columns ",
815
+ columns === 0 ? 0 : 1,
816
+ "–",
817
+ columns,
818
+ " of ",
819
+ document.columns
820
+ ]
821
+ }),
822
+ /* @__PURE__ */ jsx(Text, {
823
+ style: styles$2.copy,
824
+ children: "Scroll within the preview. Load more rows or columns when you need them."
825
+ }),
826
+ /* @__PURE__ */ jsx(ScrollView, {
827
+ style: styles$2.preview,
828
+ nestedScrollEnabled: true,
829
+ children: /* @__PURE__ */ jsx(ScrollView, {
830
+ horizontal: true,
831
+ children: /* @__PURE__ */ jsxs(View, { children: [/* @__PURE__ */ jsx(View, {
832
+ style: styles$2.tableRow,
833
+ children: Array.from({ length: columns }, (_, column) => /* @__PURE__ */ jsxs(Text, {
834
+ selectable: true,
835
+ style: styles$2.cell,
836
+ children: ["Column ", column + 1]
837
+ }, column))
838
+ }), cells.map((values, row) => /* @__PURE__ */ jsx(View, {
839
+ style: styles$2.tableRow,
840
+ children: Array.from({ length: columns }, (_, column) => /* @__PURE__ */ jsx(Text, {
841
+ selectable: true,
842
+ style: styles$2.cell,
843
+ children: values[column] ?? ""
844
+ }, column))
845
+ }, row))] })
846
+ })
847
+ }),
848
+ /* @__PURE__ */ jsx(Button, {
849
+ variant: "outline",
850
+ size: "card",
851
+ disabled: rows === rowCount,
852
+ onPress: () => setWindow({
853
+ ...current,
854
+ rows: rows + 20
855
+ }),
856
+ children: rows === rowCount ? "All rows shown" : `Show ${Math.min(20, rowCount - rows)} more rows`
857
+ }),
858
+ /* @__PURE__ */ jsx(Button, {
859
+ variant: "ghost",
860
+ size: "card",
861
+ disabled: columns === document.columns,
862
+ onPress: () => setWindow({
863
+ ...current,
864
+ columns: columns + 8
865
+ }),
866
+ children: columns === document.columns ? "All columns shown" : `Show ${Math.min(8, document.columns - columns)} more columns`
867
+ })
868
+ ]
869
+ });
870
+ });
871
+ const styles$2 = StyleSheet.create((theme) => ({
872
+ body: {
873
+ flex: 1,
874
+ padding: theme.spacing(4),
875
+ gap: theme.spacing(4),
876
+ uni__dependencies: [0]
877
+ },
878
+ copy: {
879
+ fontFamily: fontOf(theme.fontFamily.sans),
880
+ fontSize: theme.fontSize.lg,
881
+ lineHeight: theme.spacing(6),
882
+ color: theme.colors.text,
883
+ uni__dependencies: [0]
884
+ },
885
+ meta: {
886
+ fontFamily: fontOf(theme.fontFamily.sans),
887
+ fontSize: theme.fontSize.sm,
888
+ lineHeight: theme.spacing(4.5),
889
+ color: theme.colors.dim,
890
+ uni__dependencies: [0]
891
+ },
892
+ preview: {
893
+ flex: 1,
894
+ borderWidth: 1,
895
+ borderColor: theme.colors["border-soft"],
896
+ borderRadius: theme.borderRadius.md,
897
+ uni__dependencies: [0]
898
+ },
899
+ tableRow: { flexDirection: "row" },
900
+ cell: {
901
+ width: theme.spacing(36),
902
+ padding: theme.spacing(2),
903
+ borderRightWidth: 1,
904
+ borderBottomWidth: 1,
905
+ borderColor: theme.colors["border-soft"],
906
+ fontFamily: fontOf(theme.fontFamily.mono),
907
+ fontSize: theme.fontSize.sm,
908
+ color: theme.colors.text,
909
+ uni__dependencies: [0]
910
+ }
911
+ }));
912
+ //#endregion
727
913
  //#region src/extensions/workspaces/sessions/(frontend)/_components/WorkflowPanel.native.tsx
728
914
  function useWorkflows(sessionId) {
729
915
  const subscribe = useCallback((listener) => {
@@ -1332,61 +1518,66 @@ function ArtifactPreview({ sessionId, workspace, runKey, path, renderFilePreview
1332
1518
  setSaving(false);
1333
1519
  }
1334
1520
  };
1335
- return /* @__PURE__ */ jsxs(ScrollView, {
1336
- contentContainerStyle: styles$1.body,
1337
- children: [
1338
- /* @__PURE__ */ jsx(Text, {
1339
- style: styles$1.title,
1340
- children: path
1341
- }),
1521
+ const delimited = !raw && content?.text !== void 0 && /\.(csv|tsv)$/i.test(path);
1522
+ const preview = /* @__PURE__ */ jsxs(Fragment, { children: [
1523
+ /* @__PURE__ */ jsx(Text, {
1524
+ style: styles$1.title,
1525
+ children: path
1526
+ }),
1527
+ /* @__PURE__ */ jsx(Button, {
1528
+ variant: "outline",
1529
+ disabled: !nativeSaveFile || saving,
1530
+ onPress: () => void download(),
1531
+ children: "Download"
1532
+ }),
1533
+ saving ? /* @__PURE__ */ jsx(Button, {
1534
+ variant: "ghost",
1535
+ onPress: () => downloadController.current?.abort(),
1536
+ children: "Cancel download"
1537
+ }) : null,
1538
+ saveNote ? /* @__PURE__ */ jsx(Text, {
1539
+ style: styles$1.meta,
1540
+ children: saveNote
1541
+ }) : null,
1542
+ error ? /* @__PURE__ */ jsx(Text, {
1543
+ style: styles$1.error,
1544
+ children: error
1545
+ }) : null,
1546
+ content?.text !== void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
1342
1547
  /* @__PURE__ */ jsx(Button, {
1343
1548
  variant: "outline",
1344
- disabled: !nativeSaveFile || saving,
1345
- onPress: () => void download(),
1346
- children: "Download"
1549
+ onPress: () => setRaw((value) => !value),
1550
+ children: raw ? "Preview" : "Raw source"
1347
1551
  }),
1348
- saving ? /* @__PURE__ */ jsx(Button, {
1349
- variant: "ghost",
1350
- onPress: () => downloadController.current?.abort(),
1351
- children: "Cancel download"
1352
- }) : null,
1353
- saveNote ? /* @__PURE__ */ jsx(Text, {
1552
+ !raw && /\.(md|markdown)$/i.test(path) ? /* @__PURE__ */ jsx(Markdown, { text: content.text }) : !raw && /\.(html|htm)$/i.test(path) ? renderFilePreview?.({
1553
+ key: `${sessionId}:${workspace}:${runKey}:${path}`,
1554
+ html: content.text,
1555
+ title: path
1556
+ }) : !raw && /\.(csv|tsv)$/i.test(path) ? /* @__PURE__ */ jsx(DelimitedArtifact, {
1557
+ text: content.text,
1558
+ delimiter: /\.csv$/i.test(path) ? "," : " "
1559
+ }) : /* @__PURE__ */ jsx(CodeBlock, { text: !raw && /\.json$/i.test(path) ? prettyJson(content.text) : content.text }),
1560
+ content.truncated ? /* @__PURE__ */ jsx(Text, {
1354
1561
  style: styles$1.meta,
1355
- children: saveNote
1356
- }) : null,
1357
- error ? /* @__PURE__ */ jsx(Text, {
1358
- style: styles$1.error,
1359
- children: error
1360
- }) : null,
1361
- content?.text !== void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
1362
- /* @__PURE__ */ jsx(Button, {
1363
- variant: "outline",
1364
- onPress: () => setRaw((value) => !value),
1365
- children: raw ? "Preview" : "Raw source"
1366
- }),
1367
- !raw && /\.(md|markdown)$/i.test(path) ? /* @__PURE__ */ jsx(Markdown, { text: content.text }) : !raw && /\.(html|htm)$/i.test(path) ? renderFilePreview?.({
1368
- key: `${sessionId}:${workspace}:${runKey}:${path}`,
1369
- html: content.text,
1370
- title: path
1371
- }) : !raw && /\.(csv|tsv)$/i.test(path) ? /* @__PURE__ */ jsx(DelimitedArtifact, {
1372
- text: content.text,
1373
- delimiter: /\.csv$/i.test(path) ? "," : " "
1374
- }) : /* @__PURE__ */ jsx(CodeBlock, { text: !raw && /\.json$/i.test(path) ? prettyJson(content.text) : content.text }),
1375
- content.truncated ? /* @__PURE__ */ jsx(Text, {
1376
- style: styles$1.meta,
1377
- children: "This preview was truncated."
1378
- }) : null
1379
- ] }) : content ? /* @__PURE__ */ jsx(BinaryArtifactPreview, {
1380
- sessionId,
1381
- workspace,
1382
- runKey,
1383
- path,
1384
- renderMediaPreview
1385
- }) : /* @__PURE__ */ jsx(Text, {
1386
- style: styles$1.meta,
1387
- children: "Loading preview…"
1388
- })
1389
- ]
1562
+ children: "This preview was truncated."
1563
+ }) : null
1564
+ ] }) : content ? /* @__PURE__ */ jsx(BinaryArtifactPreview, {
1565
+ sessionId,
1566
+ workspace,
1567
+ runKey,
1568
+ path,
1569
+ renderMediaPreview
1570
+ }) : /* @__PURE__ */ jsx(Text, {
1571
+ style: styles$1.meta,
1572
+ children: "Loading preview…"
1573
+ })
1574
+ ] });
1575
+ return delimited ? /* @__PURE__ */ jsx(View, {
1576
+ style: [styles$1.body, styles$1.transcript],
1577
+ children: preview
1578
+ }) : /* @__PURE__ */ jsx(ScrollView, {
1579
+ contentContainerStyle: styles$1.body,
1580
+ children: preview
1390
1581
  });
1391
1582
  }
1392
1583
  function BinaryArtifactPreview({ sessionId, workspace, runKey, path, renderMediaPreview }) {
@@ -1437,41 +1628,6 @@ function prettyJson(text) {
1437
1628
  return text;
1438
1629
  }
1439
1630
  }
1440
- function DelimitedArtifact({ text, delimiter }) {
1441
- const rows = [];
1442
- let row = [];
1443
- let cell = "";
1444
- let quoted = false;
1445
- for (let index = 0; index <= text.length && rows.length < 500; index += 1) {
1446
- const character = text[index] ?? "\n";
1447
- if (quoted) {
1448
- if (character === "\"" && text[index + 1] === "\"") {
1449
- cell += "\"";
1450
- index += 1;
1451
- } else if (character === "\"") quoted = false;
1452
- else cell += character;
1453
- } else if (character === "\"" && cell === "") quoted = true;
1454
- else if (character === delimiter) {
1455
- row.push(cell);
1456
- cell = "";
1457
- } else if (character === "\n") {
1458
- row.push(cell.replace(/\r$/, ""));
1459
- rows.push(row);
1460
- row = [];
1461
- cell = "";
1462
- } else cell += character;
1463
- }
1464
- return /* @__PURE__ */ jsx(ScrollView, {
1465
- horizontal: true,
1466
- children: /* @__PURE__ */ jsx(View, { children: rows.map((cells, index) => /* @__PURE__ */ jsx(View, {
1467
- style: styles$1.tableRow,
1468
- children: cells.map((value, column) => /* @__PURE__ */ jsx(Text, {
1469
- style: styles$1.tableCell,
1470
- children: value
1471
- }, column))
1472
- }, index)) })
1473
- });
1474
- }
1475
1631
  const styles$1 = StyleSheet.create((theme) => ({
1476
1632
  screen: {
1477
1633
  flex: 1,
@@ -1480,16 +1636,6 @@ const styles$1 = StyleSheet.create((theme) => ({
1480
1636
  uni__dependencies: [0]
1481
1637
  },
1482
1638
  transcript: { flex: 1 },
1483
- tableRow: { flexDirection: "row" },
1484
- tableCell: {
1485
- color: theme.colors.text,
1486
- fontSize: theme.fontSize.sm,
1487
- padding: theme.spacing(2),
1488
- width: theme.spacing(30),
1489
- borderWidth: 1,
1490
- borderColor: theme.colors.border,
1491
- uni__dependencies: [0]
1492
- },
1493
1639
  body: {
1494
1640
  padding: theme.spacing(3),
1495
1641
  gap: theme.spacing(2),