@arbidocs/blocks 0.4.73 → 0.4.75

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.
Files changed (104) hide show
  1. package/README.md +2 -1
  2. package/dist/agents/index.cjs +255 -254
  3. package/dist/agents/index.js +5 -4
  4. package/dist/agents/workflows/WorkflowRunner.d.ts +20 -4
  5. package/dist/agents/workflows/WorkflowStepBar.d.ts +23 -0
  6. package/dist/agents/workflows/run.d.ts +1 -0
  7. package/dist/agents/workflows/types.d.ts +2 -0
  8. package/dist/chat/index.cjs +124 -124
  9. package/dist/chat/index.js +3 -3
  10. package/dist/{chunk-3SFFTSOI.cjs → chunk-7CVF3DK2.cjs} +5 -5
  11. package/dist/{chunk-3SFFTSOI.cjs.map → chunk-7CVF3DK2.cjs.map} +1 -1
  12. package/dist/{chunk-V3L5DONY.cjs → chunk-B4SRYJLM.cjs} +31 -2
  13. package/dist/chunk-B4SRYJLM.cjs.map +1 -0
  14. package/dist/{chunk-IUR565UW.cjs → chunk-F4LUD3YC.cjs} +49 -48
  15. package/dist/chunk-F4LUD3YC.cjs.map +1 -0
  16. package/dist/{chunk-WOYUXVVQ.cjs → chunk-HITAN7JF.cjs} +4 -4
  17. package/dist/{chunk-WOYUXVVQ.cjs.map → chunk-HITAN7JF.cjs.map} +1 -1
  18. package/dist/{chunk-3VQYJBOI.js → chunk-HOXKR26S.js} +31 -4
  19. package/dist/chunk-HOXKR26S.js.map +1 -0
  20. package/dist/{chunk-KJ3QEKOJ.cjs → chunk-IPGKTUF7.cjs} +7 -33
  21. package/dist/chunk-IPGKTUF7.cjs.map +1 -0
  22. package/dist/{chunk-IA7RTPT3.cjs → chunk-IXALYQT7.cjs} +2 -200
  23. package/dist/chunk-IXALYQT7.cjs.map +1 -0
  24. package/dist/{chunk-QDNXEB3T.js → chunk-LT2UORRG.js} +7 -6
  25. package/dist/chunk-LT2UORRG.js.map +1 -0
  26. package/dist/{chunk-ORA2XE7U.js → chunk-MK6NJQGF.js} +3 -3
  27. package/dist/{chunk-ORA2XE7U.js.map → chunk-MK6NJQGF.js.map} +1 -1
  28. package/dist/chunk-NUNKSZKU.js +203 -0
  29. package/dist/chunk-NUNKSZKU.js.map +1 -0
  30. package/dist/{chunk-6OL5S7MJ.cjs → chunk-NYBIKDWI.cjs} +5 -2
  31. package/dist/chunk-NYBIKDWI.cjs.map +1 -0
  32. package/dist/{chunk-GTNUQBXI.cjs → chunk-P2RBE3FD.cjs} +254 -102
  33. package/dist/chunk-P2RBE3FD.cjs.map +1 -0
  34. package/dist/{chunk-D46ZAPEE.js → chunk-R3PDNQYT.js} +5 -2
  35. package/dist/chunk-R3PDNQYT.js.map +1 -0
  36. package/dist/{chunk-G5DP27DU.js → chunk-UIWLDSTF.js} +3 -29
  37. package/dist/chunk-UIWLDSTF.js.map +1 -0
  38. package/dist/chunk-V4ISCZJ7.cjs +207 -0
  39. package/dist/chunk-V4ISCZJ7.cjs.map +1 -0
  40. package/dist/{chunk-VRPRAU3J.js → chunk-WJEKRSPH.js} +3 -3
  41. package/dist/{chunk-VRPRAU3J.js.map → chunk-WJEKRSPH.js.map} +1 -1
  42. package/dist/{chunk-2P3T23C7.js → chunk-YWYVIQ7T.js} +256 -104
  43. package/dist/chunk-YWYVIQ7T.js.map +1 -0
  44. package/dist/{chunk-BUHKUKKB.js → chunk-ZPLG7QYF.js} +4 -199
  45. package/dist/chunk-ZPLG7QYF.js.map +1 -0
  46. package/dist/connect/index.cjs +96 -37
  47. package/dist/connect/index.cjs.map +1 -1
  48. package/dist/connect/index.js +81 -22
  49. package/dist/connect/index.js.map +1 -1
  50. package/dist/connection/ConnectedWorkflowRunner.d.ts +5 -1
  51. package/dist/connection/useWorkflowThread.d.ts +4 -0
  52. package/dist/databases/DatabaseColumnDialog.d.ts +43 -0
  53. package/dist/databases/DatabaseList.d.ts +28 -0
  54. package/dist/databases/DatabaseTable.d.ts +38 -0
  55. package/dist/databases/DatabaseToolbar.d.ts +38 -0
  56. package/dist/databases/NewDatabaseDialog.d.ts +25 -0
  57. package/dist/databases/SelectCellEditor.d.ts +6 -0
  58. package/dist/databases/SelectChip.d.ts +4 -0
  59. package/dist/databases/column-types.d.ts +58 -0
  60. package/dist/databases/databaseColumns.d.ts +28 -0
  61. package/dist/databases/index.cjs +1081 -0
  62. package/dist/databases/index.cjs.map +1 -0
  63. package/dist/databases/index.d.ts +13 -0
  64. package/dist/databases/index.js +1055 -0
  65. package/dist/databases/index.js.map +1 -0
  66. package/dist/facts/index.cjs +7 -6
  67. package/dist/facts/index.cjs.map +1 -1
  68. package/dist/facts/index.js +3 -2
  69. package/dist/facts/index.js.map +1 -1
  70. package/dist/files/index.cjs +14 -13
  71. package/dist/files/index.cjs.map +1 -1
  72. package/dist/files/index.js +4 -2
  73. package/dist/files/index.js.map +1 -1
  74. package/dist/index.cjs +632 -631
  75. package/dist/index.cjs.map +1 -1
  76. package/dist/index.js +12 -11
  77. package/dist/index.js.map +1 -1
  78. package/dist/settings/index.cjs +1 -1
  79. package/dist/settings/index.js +1 -1
  80. package/dist/shell/ActionCluster.d.ts +3 -1
  81. package/dist/shell/index.cjs +45 -45
  82. package/dist/shell/index.js +1 -1
  83. package/dist/studio/index.cjs +4 -4
  84. package/dist/studio/index.js +3 -3
  85. package/dist/workflow-canvas/StepInspector.d.ts +11 -0
  86. package/dist/workflow-canvas/WorkflowCanvas.d.ts +6 -2
  87. package/dist/workflow-canvas/index.cjs +202 -91
  88. package/dist/workflow-canvas/index.cjs.map +1 -1
  89. package/dist/workflow-canvas/index.js +170 -59
  90. package/dist/workflow-canvas/index.js.map +1 -1
  91. package/dist/workflow-canvas/viewport.d.ts +47 -0
  92. package/package.json +9 -4
  93. package/dist/chunk-2P3T23C7.js.map +0 -1
  94. package/dist/chunk-3VQYJBOI.js.map +0 -1
  95. package/dist/chunk-6OL5S7MJ.cjs.map +0 -1
  96. package/dist/chunk-BUHKUKKB.js.map +0 -1
  97. package/dist/chunk-D46ZAPEE.js.map +0 -1
  98. package/dist/chunk-G5DP27DU.js.map +0 -1
  99. package/dist/chunk-GTNUQBXI.cjs.map +0 -1
  100. package/dist/chunk-IA7RTPT3.cjs.map +0 -1
  101. package/dist/chunk-IUR565UW.cjs.map +0 -1
  102. package/dist/chunk-KJ3QEKOJ.cjs.map +0 -1
  103. package/dist/chunk-QDNXEB3T.js.map +0 -1
  104. package/dist/chunk-V3L5DONY.cjs.map +0 -1
@@ -3,6 +3,7 @@
3
3
 
4
4
  var chunkDETZZBG2_cjs = require('./chunk-DETZZBG2.cjs');
5
5
  var chunk7D737FLE_cjs = require('./chunk-7D737FLE.cjs');
6
+ var chunkB4SRYJLM_cjs = require('./chunk-B4SRYJLM.cjs');
6
7
  var chunkMHVNT4J3_cjs = require('./chunk-MHVNT4J3.cjs');
7
8
  var react = require('react');
8
9
  var ui = require('@arbidocs/react/ui');
@@ -599,7 +600,13 @@ function stepStatesFromActivity(events) {
599
600
  if (!status || typeof step !== "string") continue;
600
601
  const responseId = typeof e.detail?.response_id === "string" ? e.detail.response_id : void 0;
601
602
  const error = typeof e.detail?.error === "string" ? e.detail.error : null;
602
- states[step] = { status, responseId: responseId ?? states[step]?.responseId ?? null, error };
603
+ const startedAt = status === "running" ? e.created_at : states[step]?.startedAt;
604
+ states[step] = {
605
+ status,
606
+ responseId: responseId ?? states[step]?.responseId ?? null,
607
+ error,
608
+ ...startedAt ? { startedAt } : {}
609
+ };
603
610
  }
604
611
  return states;
605
612
  }
@@ -805,6 +812,15 @@ function useWorkflowView(options) {
805
812
  },
806
813
  [steps]
807
814
  );
815
+ const onward = react.useCallback(
816
+ (id) => {
817
+ const { steps: s, states: st } = optionsRef.current;
818
+ const i = s.findIndex((x) => x.id === id);
819
+ const open = s.slice(i + 1).find((x) => !["done", "skipped"].includes(st[x.id]?.status ?? "pending"));
820
+ return open?.id ?? following(id);
821
+ },
822
+ [following]
823
+ );
808
824
  const action = busy ? "wait" : nextAction(steps, states, current);
809
825
  const next = react.useCallback(async () => {
810
826
  const { steps: s, states: st, inputs: values } = optionsRef.current;
@@ -826,13 +842,13 @@ function useWorkflowView(options) {
826
842
  await optionsRef.current.complete(at);
827
843
  }
828
844
  setShowErrors(false);
829
- setCurrent(following(current) ?? current);
845
+ setCurrent(onward(at.id) ?? current);
830
846
  } catch (e) {
831
847
  setActionError(errorMessage(e));
832
848
  } finally {
833
849
  setBusy(false);
834
850
  }
835
- }, [current, busy, following]);
851
+ }, [current, busy, following, onward]);
836
852
  const goTo = react.useCallback((stepId) => {
837
853
  setShowErrors(false);
838
854
  setActionError(null);
@@ -858,9 +874,16 @@ function useWorkflowView(options) {
858
874
  }),
859
875
  []
860
876
  );
877
+ const currentRef = react.useRef(current);
878
+ currentRef.current = current;
861
879
  const skip = react.useMemo(
862
- () => act((id) => optionsRef.current.skip(id)),
863
- [act]
880
+ () => act(async (id) => {
881
+ await optionsRef.current.skip(id);
882
+ if (currentRef.current !== id) return;
883
+ setShowErrors(false);
884
+ setCurrent(onward(id) ?? id);
885
+ }),
886
+ [act, onward]
864
887
  );
865
888
  const retry = react.useMemo(
866
889
  () => options.retry ? act((id) => optionsRef.current.retry?.(id) ?? Promise.resolve()) : void 0,
@@ -900,59 +923,38 @@ function useWorkflowView(options) {
900
923
  }
901
924
  };
902
925
  }
903
- var DEFAULT_WORKFLOW_RUNNER_LABELS = {
904
- back: "Back",
905
- next: "Continue",
906
- skip: "Skip",
907
- skipStep: "Skip this step",
908
- finish: "Finish",
909
- approve: "Approve",
910
- working: "Working\u2026",
911
- starting: "Starting\u2026",
912
- retry: "Retry",
913
- failed: "This step did not finish.",
914
- blocked: "Starts after {steps}.",
915
- awaitingReview: "Waiting for approval.",
916
- approved: "Approved.",
917
- skipped: "Skipped.",
918
- branch: "Runs alongside; its result joins the thread",
919
- complete: "Done",
920
- restart: "Start again",
921
- filesHeading: "Files ({count})",
922
- noFiles: "No files yet."
923
- };
924
926
  function PhaseMark({ phase, icon }) {
925
- if (phase === "done") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3.5" });
926
- if (phase === "running") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-3.5 animate-spin" });
927
- if (phase === "failed") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "size-3.5" });
928
- if (phase === "skipped") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MinusCircle, { className: "size-3.5" });
929
- return icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-3.5 items-center justify-center [&_svg]:size-3.5", children: icon }) : null;
927
+ if (phase === "done") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3.5 shrink-0" });
928
+ if (phase === "running") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-3.5 shrink-0 animate-spin" });
929
+ if (phase === "failed") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "size-3.5 shrink-0" });
930
+ if (phase === "skipped") return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MinusCircle, { className: "size-3.5 shrink-0" });
931
+ return icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-3.5 shrink-0 items-center justify-center [&_svg]:size-3.5", children: icon }) : null;
930
932
  }
931
- function WorkflowRunner({
932
- workflow,
933
+ var PILL = "flex min-w-0 max-w-full shrink-0 items-center gap-2 whitespace-nowrap rounded-full border px-2.5 py-1.5 text-xs font-medium";
934
+ var LABEL = "min-w-0 max-w-[12rem] truncate";
935
+ function WorkflowStepBar({
933
936
  run,
934
- renderAgentOutput,
935
- renderReview,
936
- onUpload,
937
- uploading = false,
938
- files,
939
- renderUpload,
940
- renderStepNote,
941
- renderComplete,
942
- renderScope,
943
- renderDocuments,
944
- renderIcon,
945
- labels,
946
- testIdPrefix = "workflow-run",
947
- className
937
+ levels,
938
+ doneTitle,
939
+ doneIcon,
940
+ icon,
941
+ tid
948
942
  }) {
949
- const l = { ...DEFAULT_WORKFLOW_RUNNER_LABELS, ...labels };
950
- const { steps, step, isComplete, action } = run;
951
- const completion = workflow.run.kind === "steps" ? workflow.run.completion : void 0;
952
- const tid = (suffix) => `${testIdPrefix}-${suffix}`;
953
- const levels = stepLevels(steps);
954
- const crowded = levels.length > 6;
955
- const icon = (key) => key && renderIcon ? renderIcon(key) : void 0;
943
+ const box = react.useRef(null);
944
+ const measure = react.useRef(null);
945
+ const row = react.useRef(null);
946
+ const { width } = chunkB4SRYJLM_cjs.useElementSize(box);
947
+ const [compact3, setCompact] = react.useState(false);
948
+ const titles = levels.map((l) => l.map((s) => s.title).join("\0")).join("") + doneTitle;
949
+ react.useLayoutEffect(() => {
950
+ const needed = measure.current?.scrollWidth ?? 0;
951
+ setCompact(width > 0 && needed > width);
952
+ }, [width, titles]);
953
+ react.useLayoutEffect(() => {
954
+ if (!compact3) return;
955
+ const el = row.current?.querySelector('[aria-current="step"]');
956
+ el?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
957
+ }, [compact3, run.current]);
956
958
  const pill = (s) => {
957
959
  const phase = run.phaseOf(s.id);
958
960
  const current = s.id === run.current;
@@ -963,7 +965,8 @@ function WorkflowRunner({
963
965
  onClick: () => run.goTo(s.id),
964
966
  disabled: run.busy,
965
967
  className: ui.cn(
966
- "flex shrink-0 items-center gap-2 whitespace-nowrap rounded-full border px-2.5 py-1.5 text-xs font-medium transition-colors disabled:cursor-default",
968
+ PILL,
969
+ "transition-colors disabled:cursor-default",
967
970
  current ? "border-primary bg-primary/10 text-primary" : phase === "failed" ? "border-destructive/40 text-destructive" : phase === "done" || phase === "skipped" || phase === "running" ? "border-primary/30 bg-primary/5 text-primary" : "border-border text-muted-foreground"
968
971
  ),
969
972
  "aria-current": current ? "step" : void 0,
@@ -973,47 +976,65 @@ function WorkflowRunner({
973
976
  "data-testid": tid(`step-${s.id}`),
974
977
  children: [
975
978
  /* @__PURE__ */ jsxRuntime.jsx(PhaseMark, { phase, icon: icon(s.icon) }),
976
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: ui.cn(current ? "inline" : crowded ? "hidden" : "hidden @4xl:inline"), children: s.title })
979
+ (current || !compact3) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: LABEL, "data-testid": tid(`step-${s.id}-label`), children: s.title })
977
980
  ]
978
981
  },
979
982
  s.id
980
983
  );
981
984
  };
982
- const nextLabel = action === "skip" ? l.skip : action === "finish" ? l.finish : action === "complete" && step?.kind === "review" ? l.approve : action === "wait" && (run.isRunning || run.busy) ? l.working : (step && !run.isLocked(step.id) ? step.nextLabel : void 0) ?? l.next;
983
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn("space-y-6", className), "data-testid": testIdPrefix, children: [
984
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "@container", children: /* @__PURE__ */ jsxRuntime.jsx(
985
+ const done = run.isComplete;
986
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: box, className: "relative min-w-0", children: [
987
+ /* @__PURE__ */ jsxRuntime.jsx(
988
+ "div",
989
+ {
990
+ ref: measure,
991
+ "aria-hidden": true,
992
+ className: "pointer-events-none invisible absolute left-0 top-0 flex w-max items-center gap-1.5",
993
+ children: [...levels, [{ id: "__done", title: doneTitle }]].map((level, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
994
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-start gap-1", children: level.map((s) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: PILL, children: [
995
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-3.5 shrink-0" }),
996
+ /* @__PURE__ */ jsxRuntime.jsx(
997
+ "span",
998
+ {
999
+ className: ui.cn(LABEL, "before:content-[attr(data-label)]"),
1000
+ "data-label": s.title
1001
+ }
1002
+ )
1003
+ ] }, s.id)) }),
1004
+ i < levels.length && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2" })
1005
+ ] }, i))
1006
+ }
1007
+ ),
1008
+ /* @__PURE__ */ jsxRuntime.jsx(
985
1009
  "ol",
986
1010
  {
987
- className: ui.cn("flex w-full items-center gap-1.5", crowded && "overflow-x-auto pb-1"),
1011
+ ref: row,
1012
+ className: ui.cn("flex w-full items-center gap-1.5", compact3 && "overflow-x-auto pb-1"),
1013
+ "data-compact": compact3 || void 0,
988
1014
  "data-testid": tid("steps"),
989
1015
  children: [...levels, null].map((level, i) => /* @__PURE__ */ jsxRuntime.jsxs(
990
1016
  "li",
991
1017
  {
992
1018
  className: ui.cn(
993
- "flex items-center gap-1.5",
994
- i < levels.length && (crowded ? "flex-none" : "min-w-0 flex-1 @4xl:flex-none")
1019
+ "flex min-w-0 items-center gap-1.5",
1020
+ i < levels.length && !compact3 && "flex-1",
1021
+ compact3 && "flex-none"
995
1022
  ),
996
1023
  children: [
997
- level ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-start gap-1", children: level.map(pill) }) : /* @__PURE__ */ jsxRuntime.jsxs(
1024
+ level ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-col items-start gap-1", children: level.map(pill) }) : /* @__PURE__ */ jsxRuntime.jsxs(
998
1025
  "div",
999
1026
  {
1000
1027
  className: ui.cn(
1001
- "flex shrink-0 items-center gap-2 whitespace-nowrap rounded-full border px-2.5 py-1.5 text-xs font-medium",
1002
- isComplete ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground"
1028
+ PILL,
1029
+ done ? "border-primary bg-primary/10 text-primary" : "border-border text-muted-foreground"
1003
1030
  ),
1004
- "aria-current": isComplete ? "step" : void 0,
1031
+ "aria-current": done ? "step" : void 0,
1032
+ "aria-label": doneTitle,
1033
+ title: doneTitle,
1005
1034
  "data-testid": tid("step-done"),
1006
1035
  children: [
1007
- /* @__PURE__ */ jsxRuntime.jsx(PhaseMark, { phase: "ready", icon: icon(completion?.icon) }),
1008
- /* @__PURE__ */ jsxRuntime.jsx(
1009
- "span",
1010
- {
1011
- className: ui.cn(
1012
- isComplete ? "inline" : crowded ? "hidden" : "hidden @4xl:inline"
1013
- ),
1014
- children: completion?.title ?? l.complete
1015
- }
1016
- )
1036
+ /* @__PURE__ */ jsxRuntime.jsx(PhaseMark, { phase: "ready", icon: doneIcon }),
1037
+ (done || !compact3) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: LABEL, children: doneTitle })
1017
1038
  ]
1018
1039
  }
1019
1040
  ),
@@ -1022,7 +1043,7 @@ function WorkflowRunner({
1022
1043
  {
1023
1044
  className: ui.cn(
1024
1045
  "h-px",
1025
- crowded ? "w-3 flex-none" : "min-w-2 flex-1 @4xl:w-4 @4xl:flex-none",
1046
+ compact3 ? "w-3 flex-none" : "min-w-2 flex-1",
1026
1047
  level?.every((s) => ["done", "skipped"].includes(run.phaseOf(s.id))) ? "bg-primary/40" : "bg-border"
1027
1048
  )
1028
1049
  }
@@ -1032,7 +1053,76 @@ function WorkflowRunner({
1032
1053
  level ? level.map((s) => s.id).join("+") : "done"
1033
1054
  ))
1034
1055
  }
1035
- ) }),
1056
+ )
1057
+ ] });
1058
+ }
1059
+ var DEFAULT_WORKFLOW_RUNNER_LABELS = {
1060
+ back: "Back",
1061
+ next: "Continue",
1062
+ skip: "Skip",
1063
+ skipStep: "Skip this step",
1064
+ finish: "Finish",
1065
+ approve: "Approve",
1066
+ working: "Working\u2026",
1067
+ stepWorking: "{step}\u2026 {elapsed}",
1068
+ starting: "Starting\u2026",
1069
+ retry: "Retry",
1070
+ failed: "This step did not finish.",
1071
+ blocked: "Starts after {steps}.",
1072
+ awaitingReview: "Waiting for approval.",
1073
+ approved: "Approved.",
1074
+ skipped: "Skipped.",
1075
+ branch: "Runs alongside; its result joins the thread",
1076
+ complete: "Done",
1077
+ restart: "Start again",
1078
+ filesHeading: "Already in the workspace ({count})",
1079
+ addedHeading: "Added for this step ({count})",
1080
+ noFiles: "No files yet.",
1081
+ fileReading: "Reading\u2026",
1082
+ fileReady: "Ready",
1083
+ fileFailed: "Could not be read",
1084
+ readingFiles: "Reading {current} of {count} files\u2026"
1085
+ };
1086
+ function WorkflowRunner({
1087
+ workflow,
1088
+ run,
1089
+ renderAgentOutput,
1090
+ renderReview,
1091
+ onUpload,
1092
+ uploading = false,
1093
+ files,
1094
+ renderUpload,
1095
+ renderStepNote,
1096
+ renderComplete,
1097
+ renderScope,
1098
+ renderDocuments,
1099
+ renderIcon,
1100
+ labels,
1101
+ testIdPrefix = "workflow-run",
1102
+ className
1103
+ }) {
1104
+ const l = { ...DEFAULT_WORKFLOW_RUNNER_LABELS, ...labels };
1105
+ const { steps, step, isComplete, action } = run;
1106
+ const completion = workflow.run.kind === "steps" ? workflow.run.completion : void 0;
1107
+ const tid = (suffix) => `${testIdPrefix}-${suffix}`;
1108
+ const levels = stepLevels(steps);
1109
+ const icon = (key) => key && renderIcon ? renderIcon(key) : void 0;
1110
+ const added = step?.kind === "upload" ? (files ?? []).filter((f) => f.addedFor === step.id) : [];
1111
+ const unread = added.filter((f) => f.status === "processing").length;
1112
+ const reading = action === "complete" && unread > 0;
1113
+ const nextLabel = reading ? l.readingFiles.replace("{current}", String(Math.min(added.length - unread + 1, added.length))).replace("{count}", String(added.length)) : action === "skip" ? l.skip : action === "finish" ? l.finish : action === "complete" && step?.kind === "review" ? l.approve : action === "wait" && (run.isRunning || run.busy) ? l.working : (step && !run.isLocked(step.id) ? step.nextLabel : void 0) ?? l.next;
1114
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ui.cn("space-y-6", className), "data-testid": testIdPrefix, children: [
1115
+ /* @__PURE__ */ jsxRuntime.jsx(
1116
+ WorkflowStepBar,
1117
+ {
1118
+ run,
1119
+ levels,
1120
+ doneTitle: completion?.title ?? l.complete,
1121
+ doneIcon: icon(completion?.icon),
1122
+ icon,
1123
+ tid
1124
+ }
1125
+ ),
1036
1126
  isComplete ? renderComplete?.(run) ?? /* @__PURE__ */ jsxRuntime.jsxs(ui.Card, { className: "mx-auto max-w-lg p-8 text-center", "data-testid": tid("done"), children: [
1037
1127
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "mx-auto size-12 text-primary" }),
1038
1128
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "mt-4 text-xl font-semibold", children: completion?.title ?? l.complete }),
@@ -1051,7 +1141,7 @@ function WorkflowRunner({
1051
1141
  "{steps}",
1052
1142
  stepDependencies(steps, step.id).map((d) => steps.find((s) => s.id === d)?.title ?? d).join(", ")
1053
1143
  ) }) }) : step.kind === "form" ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Card, { className: "max-w-2xl space-y-4 p-6", "data-testid": tid(step.id), children: [
1054
- step.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: step.description }),
1144
+ /* @__PURE__ */ jsxRuntime.jsx(StepHeading, { step, icon: icon(step.icon), testId: tid(`${step.id}-title`) }),
1055
1145
  /* @__PURE__ */ jsxRuntime.jsx("fieldset", { disabled: run.isLocked(step.id), className: "contents", children: /* @__PURE__ */ jsxRuntime.jsx(
1056
1146
  SchemaForm,
1057
1147
  {
@@ -1073,7 +1163,7 @@ function WorkflowRunner({
1073
1163
  /* @__PURE__ */ jsxRuntime.jsx(
1074
1164
  chunkDETZZBG2_cjs.UploadDropzone,
1075
1165
  {
1076
- onFiles: (picked) => void onUpload?.(picked),
1166
+ onFiles: (picked) => void onUpload?.(picked, step),
1077
1167
  uploading,
1078
1168
  disabled: !onUpload,
1079
1169
  accept: step.accept,
@@ -1083,21 +1173,15 @@ function WorkflowRunner({
1083
1173
  testId: tid(`${step.id}-drop`)
1084
1174
  }
1085
1175
  ),
1086
- files && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", "data-testid": tid(`${step.id}-files`), children: [
1087
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: l.filesHeading.replace("{count}", String(files.length)) }),
1088
- files.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: l.noFiles }),
1089
- files.slice(0, 6).map((f) => /* @__PURE__ */ jsxRuntime.jsxs(
1090
- "div",
1091
- {
1092
- className: "flex items-center gap-2 text-sm text-muted-foreground",
1093
- children: [
1094
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "size-3.5 text-primary" }),
1095
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: f.name })
1096
- ]
1097
- },
1098
- f.id
1099
- ))
1100
- ] })
1176
+ files && /* @__PURE__ */ jsxRuntime.jsx(
1177
+ UploadFiles,
1178
+ {
1179
+ added,
1180
+ others: files.filter((f) => f.addedFor !== step.id),
1181
+ l,
1182
+ testId: tid(`${step.id}-files`)
1183
+ }
1184
+ )
1101
1185
  ] }),
1102
1186
  run.actionError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: run.actionError }),
1103
1187
  renderStepNote?.(step, run)
@@ -1151,11 +1235,11 @@ function WorkflowRunner({
1151
1235
  ui.Button,
1152
1236
  {
1153
1237
  onClick: () => void run.next(),
1154
- disabled: action === "wait",
1238
+ disabled: action === "wait" || reading,
1155
1239
  "data-testid": tid("next"),
1156
1240
  children: [
1157
1241
  nextLabel,
1158
- action === "wait" && (run.isRunning || run.busy) ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "size-4" })
1242
+ reading || action === "wait" && (run.isRunning || run.busy) ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-4 animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "size-4" })
1159
1243
  ]
1160
1244
  }
1161
1245
  )
@@ -1163,15 +1247,83 @@ function WorkflowRunner({
1163
1247
  ] })
1164
1248
  ] });
1165
1249
  }
1166
- function StepHeading({ step, icon }) {
1250
+ function UploadFiles({
1251
+ added,
1252
+ others,
1253
+ l,
1254
+ testId
1255
+ }) {
1256
+ const heading = "text-xs font-semibold uppercase tracking-wide text-muted-foreground";
1257
+ const row = (f) => /* @__PURE__ */ jsxRuntime.jsxs(
1258
+ "div",
1259
+ {
1260
+ className: "flex items-center gap-2 text-sm text-muted-foreground",
1261
+ "data-status": f.status,
1262
+ "data-testid": `${testId}-file-${f.id}`,
1263
+ children: [
1264
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "size-3.5 shrink-0 text-primary" }),
1265
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", title: f.name, children: f.name }),
1266
+ f.status === "processing" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-1 text-xs", children: [
1267
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-3 animate-spin" }),
1268
+ " ",
1269
+ l.fileReading
1270
+ ] }),
1271
+ f.status === "ready" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-1 text-xs text-primary", children: [
1272
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3" }),
1273
+ " ",
1274
+ l.fileReady
1275
+ ] }),
1276
+ f.status === "failed" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-1 text-xs text-destructive", children: [
1277
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "size-3" }),
1278
+ " ",
1279
+ l.fileFailed
1280
+ ] })
1281
+ ]
1282
+ },
1283
+ f.id
1284
+ );
1285
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", "data-testid": testId, children: [
1286
+ added.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", "data-testid": `${testId}-added`, children: [
1287
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: heading, children: l.addedHeading.replace("{count}", String(added.length)) }),
1288
+ added.map(row)
1289
+ ] }),
1290
+ added.length === 0 && others.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: l.noFiles }),
1291
+ others.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "space-y-1", "data-testid": `${testId}-others`, children: [
1292
+ /* @__PURE__ */ jsxRuntime.jsx("summary", { className: ui.cn(heading, "cursor-pointer select-none"), children: l.filesHeading.replace("{count}", String(others.length)) }),
1293
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 max-h-48 space-y-1 overflow-y-auto", children: others.map(row) })
1294
+ ] })
1295
+ ] });
1296
+ }
1297
+ function StepHeading({
1298
+ step,
1299
+ icon,
1300
+ testId
1301
+ }) {
1167
1302
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
1168
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-2 text-sm font-medium", children: [
1303
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-2 text-sm font-medium", "data-testid": testId, children: [
1169
1304
  icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-4 items-center justify-center text-primary [&_svg]:size-4", children: icon }),
1170
1305
  step.title
1171
1306
  ] }),
1172
1307
  step.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: step.description })
1173
1308
  ] });
1174
1309
  }
1310
+ function formatElapsed(ms) {
1311
+ const total = Math.max(0, Math.floor(ms / 1e3));
1312
+ const h = Math.floor(total / 3600);
1313
+ const m = Math.floor(total % 3600 / 60);
1314
+ const sec = String(total % 60).padStart(2, "0");
1315
+ return h ? `${h}:${String(m).padStart(2, "0")}:${sec}` : `${m}:${sec}`;
1316
+ }
1317
+ function StepWorking({ title, since, label }) {
1318
+ const seen = react.useRef(Date.now());
1319
+ const start = since && Date.parse(since) || seen.current;
1320
+ const [now, setNow] = react.useState(() => Date.now());
1321
+ react.useEffect(() => {
1322
+ const t = setInterval(() => setNow(Date.now()), 1e3);
1323
+ return () => clearInterval(t);
1324
+ }, []);
1325
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { children: label.replace("{step}", title).replace("{elapsed}", formatElapsed(now - start)) });
1326
+ }
1175
1327
  function AgentStepBody({
1176
1328
  step,
1177
1329
  run,
@@ -1215,7 +1367,7 @@ function AgentStepBody({
1215
1367
  children: [
1216
1368
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-4 animate-spin" }),
1217
1369
  " ",
1218
- phase === "ready" ? l.starting : l.working
1370
+ phase === "ready" ? l.starting : /* @__PURE__ */ jsxRuntime.jsx(StepWorking, { title: step.title, since: state?.startedAt, label: l.stepWorking })
1219
1371
  ]
1220
1372
  }
1221
1373
  ),
@@ -1292,5 +1444,5 @@ exports.workflowFromFrontmatter = workflowFromFrontmatter;
1292
1444
  exports.workflowSteps = workflowSteps;
1293
1445
  exports.workflowsAccepting = workflowsAccepting;
1294
1446
  exports.workflowsForHost = workflowsForHost;
1295
- //# sourceMappingURL=chunk-GTNUQBXI.cjs.map
1296
- //# sourceMappingURL=chunk-GTNUQBXI.cjs.map
1447
+ //# sourceMappingURL=chunk-P2RBE3FD.cjs.map
1448
+ //# sourceMappingURL=chunk-P2RBE3FD.cjs.map