@loopstack/loopstack-studio 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/api/config.js +3 -3
  2. package/dist/api/index.js +9 -13
  3. package/dist/api/processor.js +1 -1
  4. package/dist/api/workflows.js +7 -1
  5. package/dist/components/dynamic-form/CodeContent.js +3 -3
  6. package/dist/components/dynamic-form/fields/CodeViewField.js +36 -36
  7. package/dist/components/feedback/LoadingCentered.js +1 -1
  8. package/dist/components/layout/StudioSidebar.js +2 -2
  9. package/dist/components/loopstack-elements/link.js +77 -76
  10. package/dist/components/loopstack-elements/tool.js +171 -0
  11. package/dist/components/ui-widgets/UiActions.js +10 -4
  12. package/dist/components/ui-widgets/UiWidget.js +27 -36
  13. package/dist/components/ui-widgets/widgets/ButtonFullWidth.js +8 -6
  14. package/dist/components/ui-widgets/widgets/SubmitButton.js +8 -6
  15. package/dist/features/code-explorer/components/FileContentViewer.js +87 -112
  16. package/dist/features/dashboard/RunItem.js +1 -1
  17. package/dist/features/debug/components/ConfigFlowViewer.js +2 -2
  18. package/dist/features/debug/components/{PipelineDebugHeader.js → WorkflowDebugHeader.js} +5 -5
  19. package/dist/features/debug/components/{PipelineDebugLegend.js → WorkflowDebugLegend.js} +2 -2
  20. package/dist/features/debug/components/{PipelineFlowViewer.js → WorkflowFlowViewer.js} +9 -9
  21. package/dist/features/debug/components/workflow-flow/WorkflowGraph.js +46 -0
  22. package/dist/features/debug/index.js +2 -2
  23. package/dist/features/debug/lib/flow-utils.js +142 -150
  24. package/dist/features/documents/DocumentRenderer.js +66 -30
  25. package/dist/features/documents/components/DocumentItem.js +2 -2
  26. package/dist/features/documents/components/DocumentList.js +15 -12
  27. package/dist/features/documents/document-details/DocumentDetails.js +4 -4
  28. package/dist/features/documents/renderers/AiMessage.js +1 -1
  29. package/dist/features/documents/renderers/ChoicesRenderer.js +92 -0
  30. package/dist/features/documents/renderers/ClaudeMessage.js +1 -1
  31. package/dist/features/documents/renderers/ConfirmPromptRenderer.js +56 -0
  32. package/dist/features/documents/renderers/DocumentFormRenderer.js +95 -71
  33. package/dist/features/documents/renderers/LinkMessageRenderer.js +8 -10
  34. package/dist/features/documents/renderers/SecretInputRenderer.js +87 -0
  35. package/dist/features/documents/renderers/TextPromptRenderer.js +57 -0
  36. package/dist/features/documents/renderers/useDocumentTransition.js +30 -0
  37. package/dist/features/oauth/OAuthPromptRenderer.js +20 -20
  38. package/dist/features/runs/Runs.js +8 -8
  39. package/dist/features/workbench/Workbench.js +35 -35
  40. package/dist/features/workbench/WorkflowItem.js +10 -9
  41. package/dist/features/workbench/WorkflowList.js +56 -73
  42. package/dist/features/workbench/components/NewRunDialog.js +18 -18
  43. package/dist/features/workbench/components/WorkbenchFilesPanel.js +1 -1
  44. package/dist/features/workbench/components/WorkbenchFloatingPanel.js +33 -72
  45. package/dist/features/workbench/components/WorkbenchFlowPanel.js +27 -29
  46. package/dist/features/workbench/components/WorkbenchIconSidebar.js +30 -42
  47. package/dist/features/workbench/components/WorkbenchPreviewPanel.js +2 -2
  48. package/dist/features/workbench/components/WorkbenchSecretsPanel.js +1 -1
  49. package/dist/features/workbench/components/WorkbenchSettingsModal.js +16 -41
  50. package/dist/features/workbench/components/WorkflowForms.js +14 -13
  51. package/dist/features/workbench/components/WorkflowHistoryItem.js +60 -81
  52. package/dist/features/workbench/components/{PipelineHistoryList.js → WorkflowHistoryList.js} +5 -5
  53. package/dist/features/workbench/components/buttons/WorkflowButtons.js +56 -54
  54. package/dist/features/workbench/hooks/useWorkflowData.js +10 -10
  55. package/dist/features/workbench/hooks/useWorkflowListState.js +8 -45
  56. package/dist/features/workbench/index.js +2 -3
  57. package/dist/features/workbench/providers/ScrollProvider.js +2 -2
  58. package/dist/features/workbench/providers/WorkbenchLayoutProvider.js +4 -4
  59. package/dist/features/workspaces/Workspaces.js +1 -1
  60. package/dist/features/workspaces/components/CreateWorkspace.js +12 -12
  61. package/dist/features/workspaces/components/ExecutionTimeline.js +22 -21
  62. package/dist/features/workspaces/components/{NewPipelineRunDialog.js → NewWorkflowRunDialog.js} +6 -6
  63. package/dist/features/workspaces/components/{PipelineForm.js → WorkflowRunForm.js} +31 -31
  64. package/dist/features/workspaces/components/WorkspaceHomePage.js +11 -11
  65. package/dist/features/workspaces/components/{pipeline-form → workflow-form}/ArgumentsView.js +1 -1
  66. package/dist/features/workspaces/components/{pipeline-form → workflow-form}/SelectionView.js +16 -16
  67. package/dist/hooks/index.js +3 -3
  68. package/dist/hooks/query-keys.js +31 -72
  69. package/dist/hooks/useConfig.js +5 -5
  70. package/dist/hooks/useProcessor.js +5 -5
  71. package/dist/hooks/useWorkflows.js +155 -68
  72. package/dist/index.d.ts +127 -128
  73. package/dist/index.js +5 -5
  74. package/dist/packages/contracts/dist/enums/index.js +11 -12
  75. package/dist/packages/contracts/dist/enums/workflow-state.enum.js +1 -1
  76. package/dist/pages/DebugWorkflowDetailsPage.js +8 -8
  77. package/dist/pages/DebugWorkflowsPage.js +10 -10
  78. package/dist/pages/EmbedWorkbenchPage.js +42 -52
  79. package/dist/pages/PreviewWorkbenchPage.js +130 -255
  80. package/dist/pages/RunsListPage.js +1 -1
  81. package/dist/pages/StudioLandingPage.js +13 -13
  82. package/dist/pages/WorkbenchPage.js +6 -6
  83. package/dist/pages/WorkflowDebugPage.js +114 -0
  84. package/dist/pages/WorkspacePage.js +4 -2
  85. package/dist/providers/InvalidationEventsProvider.js +19 -19
  86. package/dist/providers/SseProvider.js +0 -1
  87. package/dist/routing/LocalRouter.js +14 -17
  88. package/package.json +2 -2
  89. package/dist/api/namespaces.js +0 -7
  90. package/dist/api/pipelines.js +0 -13
  91. package/dist/components/ai-elements/tool.js +0 -158
  92. package/dist/components/ui-widgets/widgets/SecretInput.js +0 -42
  93. package/dist/features/debug/components/pipeline-flow/WorkflowGraph.js +0 -41
  94. package/dist/features/workbench/NavigationItems.js +0 -52
  95. package/dist/features/workbench/WorkbenchNavigation.js +0 -38
  96. package/dist/features/workbench/components/NavigationItem.js +0 -68
  97. package/dist/features/workbench/hooks/useIntersectionObserver.js +0 -44
  98. package/dist/hooks/useNamespaceTree.js +0 -27
  99. package/dist/hooks/useNamespaces.js +0 -25
  100. package/dist/hooks/usePipelines.js +0 -161
  101. package/dist/packages/contracts/dist/enums/pipeline-state.js +0 -10
  102. package/dist/pages/PipelineDebugPage.js +0 -115
  103. /package/dist/features/debug/components/{pipeline-flow → workflow-flow}/StateNode.js +0 -0
  104. /package/dist/features/debug/components/{pipeline-flow → workflow-flow}/WorkflowTransitionEdge.js +0 -0
  105. /package/dist/features/workspaces/components/{pipeline-form → workflow-form}/HeaderSection.js +0 -0
@@ -1,5 +1,5 @@
1
1
  import { useStudio } from "../providers/StudioProvider.js";
2
- import { useFilterPipelines } from "../hooks/usePipelines.js";
2
+ import { useFilterWorkflows } from "../hooks/useWorkflows.js";
3
3
  import { Button } from "../components/ui/button.js";
4
4
  import { NewRunDialog } from "../features/workbench/components/NewRunDialog.js";
5
5
  import "../features/workbench/index.js";
@@ -19,22 +19,22 @@ var STATUS_DOT_COLORS = {
19
19
  function StudioLandingPage() {
20
20
  let s = c(28), { router: p } = useStudio(), [m, h] = useState(!1), [v, y] = useState(3), b;
21
21
  s[0] === Symbol.for("react.memo_cache_sentinel") ? (b = { parentId: null }, s[0] = b) : b = s[0];
22
- let x = useFilterPipelines(void 0, b, "createdAt", "DESC", 0, v), S;
22
+ let x = useFilterWorkflows(void 0, b, "createdAt", "DESC", 0, v), S;
23
23
  s[1] === x.data?.data ? S = s[2] : (S = x.data?.data ?? [], s[1] = x.data?.data, s[2] = S);
24
24
  let C = S, w = x.data?.total ?? 0, T = C.length < w, E;
25
25
  s[3] === Symbol.for("react.memo_cache_sentinel") ? (E = {
26
26
  parentId: null,
27
27
  status: "paused"
28
28
  }, s[3] = E) : E = s[3];
29
- let D = useFilterPipelines(void 0, E, "createdAt", "DESC", 0, 5), O;
29
+ let D = useFilterWorkflows(void 0, E, "createdAt", "DESC", 0, 5), O;
30
30
  s[4] === D.data?.data ? O = s[5] : (O = D.data?.data ?? [], s[4] = D.data?.data, s[5] = O);
31
31
  let k = O, A;
32
32
  s[6] === p ? A = s[7] : (A = (e) => {
33
- h(!1), p.navigateToPipeline(e);
33
+ h(!1), p.navigateToWorkflow(e);
34
34
  }, s[6] = p, s[7] = A);
35
35
  let j = A, M;
36
36
  s[8] === p ? M = s[9] : (M = (e) => {
37
- p.navigateToPipeline(e);
37
+ p.navigateToWorkflow(e);
38
38
  }, s[8] = p, s[9] = M);
39
39
  let N = M, P;
40
40
  s[10] === Symbol.for("react.memo_cache_sentinel") ? (P = /* @__PURE__ */ jsx("div", {
@@ -54,7 +54,7 @@ function StudioLandingPage() {
54
54
  }), /* @__PURE__ */ jsx("div", {
55
55
  className: "divide-border divide-y",
56
56
  children: k.map((e) => /* @__PURE__ */ jsx(RecentRunItem, {
57
- pipeline: e,
57
+ workflow: e,
58
58
  onClick: () => N(e.id)
59
59
  }, e.id))
60
60
  })] }), s[11] = N, s[12] = k, s[13] = F) : F = s[13];
@@ -72,7 +72,7 @@ function StudioLandingPage() {
72
72
  children: /* @__PURE__ */ jsx("div", {
73
73
  className: "divide-border divide-y",
74
74
  children: C.map((e) => /* @__PURE__ */ jsx(RecentRunItem, {
75
- pipeline: e,
75
+ workflow: e,
76
76
  onClick: () => N(e.id)
77
77
  }, e.id))
78
78
  })
@@ -108,18 +108,18 @@ function _temp(e) {
108
108
  return e + 5;
109
109
  }
110
110
  function RecentRunItem(e) {
111
- let i = c(17), { pipeline: a, onClick: o } = e, s = `h-1.5 w-1.5 shrink-0 rounded-full ${STATUS_DOT_COLORS[a.status] ?? "bg-muted-foreground"}`, l;
111
+ let i = c(17), { workflow: a, onClick: o } = e, s = `h-1.5 w-1.5 shrink-0 rounded-full ${STATUS_DOT_COLORS[a.status] ?? "bg-muted-foreground"}`, l;
112
112
  i[0] === s ? l = i[1] : (l = /* @__PURE__ */ jsx("span", { className: s }), i[0] = s, i[1] = l);
113
113
  let u;
114
- i[2] !== a.blockName || i[3] !== a.run ? (u = /* @__PURE__ */ jsxs("span", {
114
+ i[2] !== a.alias || i[3] !== a.run ? (u = /* @__PURE__ */ jsxs("span", {
115
115
  className: "truncate text-sm font-medium",
116
116
  children: [
117
117
  "Run #",
118
118
  a.run,
119
119
  " · ",
120
- a.blockName
120
+ a.alias
121
121
  ]
122
- }), i[2] = a.blockName, i[3] = a.run, i[4] = u) : u = i[4];
122
+ }), i[2] = a.alias, i[3] = a.run, i[4] = u) : u = i[4];
123
123
  let d;
124
124
  i[5] !== l || i[6] !== u ? (d = /* @__PURE__ */ jsxs("div", {
125
125
  className: "flex items-center gap-2",
@@ -128,14 +128,14 @@ function RecentRunItem(e) {
128
128
  let f = a.status, h;
129
129
  i[8] === a.createdAt ? h = i[9] : (h = formatDistanceToNow(new Date(a.createdAt), { addSuffix: !0 }), i[8] = a.createdAt, i[9] = h);
130
130
  let g;
131
- i[10] !== a.status || i[11] !== h ? (g = /* @__PURE__ */ jsxs("p", {
131
+ i[10] !== h || i[11] !== a.status ? (g = /* @__PURE__ */ jsxs("p", {
132
132
  className: "text-muted-foreground mt-0.5 pl-3.5 text-xs",
133
133
  children: [
134
134
  f,
135
135
  " · ",
136
136
  h
137
137
  ]
138
- }), i[10] = a.status, i[11] = h, i[12] = g) : g = i[12];
138
+ }), i[10] = h, i[11] = a.status, i[12] = g) : g = i[12];
139
139
  let _;
140
140
  return i[13] !== o || i[14] !== d || i[15] !== g ? (_ = /* @__PURE__ */ jsxs("button", {
141
141
  className: "hover:bg-accent w-full rounded-md px-2 py-2.5 text-left transition-colors",
@@ -1,5 +1,5 @@
1
1
  import { useStudio } from "../providers/StudioProvider.js";
2
- import { usePipeline } from "../hooks/usePipelines.js";
2
+ import { useWorkflow } from "../hooks/useWorkflows.js";
3
3
  import { useWorkspace } from "../hooks/useWorkspaces.js";
4
4
  import LoadingCentered_default from "../components/feedback/LoadingCentered.js";
5
5
  import ErrorSnackbar_default from "../components/feedback/ErrorSnackbar.js";
@@ -15,8 +15,8 @@ function WorkbenchPage(m) {
15
15
  let h = c(45), g;
16
16
  h[0] === m ? g = h[1] : (g = m === void 0 ? {} : m, h[0] = m, h[1] = g);
17
17
  let { previewPanelOpen: _, onPreviewPanelOpenChange: v, isDeveloperMode: y, getPreviewUrl: b, getEnvironmentPreviewUrl: x, environments: S } = g, { router: C } = useStudio(), w = useParams(), T;
18
- h[2] === w ? T = h[3] : (T = requireParam(w, "pipelineId"), h[2] = w, h[3] = T);
19
- let E = usePipeline(T), D = E.data?.workspaceId, O = useWorkspace(D);
18
+ h[2] === w ? T = h[3] : (T = requireParam(w, "workflowId"), h[2] = w, h[3] = T);
19
+ let E = useWorkflow(T), D = E.data?.workspaceId, O = useWorkspace(D);
20
20
  O.data?.environments;
21
21
  let k = S ?? O.data?.environments, A = x ?? _temp, j;
22
22
  h[4] === C ? j = h[5] : (j = C.getDashboard(), h[4] = C, h[5] = j);
@@ -55,7 +55,7 @@ function WorkbenchPage(m) {
55
55
  h[26] === E.error ? U = h[27] : (U = /* @__PURE__ */ jsx(ErrorSnackbar_default, { error: E.error }), h[26] = E.error, h[27] = U);
56
56
  let W;
57
57
  h[28] !== H || h[29] !== E.data || h[30] !== E.error || h[31] !== E.isLoading || h[32] !== b || h[33] !== y || h[34] !== v || h[35] !== _ || h[36] !== k || h[37] !== A ? (W = E.data ? /* @__PURE__ */ jsx(Workbench, {
58
- pipeline: E.data,
58
+ workflow: E.data,
59
59
  breadcrumbData: H,
60
60
  previewPanelOpen: _,
61
61
  onPreviewPanelOpenChange: v,
@@ -65,7 +65,7 @@ function WorkbenchPage(m) {
65
65
  environments: k
66
66
  }) : !E.isLoading && !E.error ? /* @__PURE__ */ jsx("p", {
67
67
  className: "text-muted-foreground py-8 text-center text-sm",
68
- children: "Pipeline not found."
68
+ children: "Workflow not found."
69
69
  }) : null, h[28] = H, h[29] = E.data, h[30] = E.error, h[31] = E.isLoading, h[32] = b, h[33] = y, h[34] = v, h[35] = _, h[36] = k, h[37] = A, h[38] = W) : W = h[38];
70
70
  let G;
71
71
  h[39] !== E.isLoading || h[40] !== W ? (G = /* @__PURE__ */ jsx(LoadingCentered_default, {
@@ -87,6 +87,6 @@ function _temp(t, f) {
87
87
  url: t.connectionUrl,
88
88
  name: t.envName || t.workerId || ""
89
89
  });
90
- return f ? `/embed/env/preview/pipelines/${f}?${p}` : `/embed/env/preview?${p}`;
90
+ return f ? `/embed/env/preview/workflows/${f}?${p}` : `/embed/env/preview?${p}`;
91
91
  }
92
92
  export { WorkbenchPage as default };
@@ -0,0 +1,114 @@
1
+ import { useStudio } from "../providers/StudioProvider.js";
2
+ import { useChildWorkflows, useWorkflow, useWorkflowConfigByName } from "../hooks/useWorkflows.js";
3
+ import { useWorkspace } from "../hooks/useWorkspaces.js";
4
+ import MainLayout_default from "../components/layout/MainLayout.js";
5
+ import ErrorSnackbar_default from "../components/feedback/ErrorSnackbar.js";
6
+ import { ReactFlowProvider } from "../node_modules/@xyflow/react/dist/esm/index.js";
7
+ import WorkflowFlowViewer_default from "../features/debug/components/WorkflowFlowViewer.js";
8
+ import WorkflowDebugHeader_default from "../features/debug/components/WorkflowDebugHeader.js";
9
+ import "../features/debug/index.js";
10
+ import { requireParam } from "../lib/requireParam.js";
11
+ import { c } from "react/compiler-runtime";
12
+ import React, { useMemo } from "react";
13
+ import { jsx, jsxs } from "react/jsx-runtime";
14
+ import { useParams } from "react-router-dom";
15
+ import { Bug, Home, Loader2 } from "lucide-react";
16
+ var WorkflowDebugPage_default = () => {
17
+ let y = c(54), { router: b } = useStudio(), x = useParams(), S;
18
+ y[0] === x ? S = y[1] : (S = requireParam(x, "workflowId"), y[0] = x, y[1] = S);
19
+ let C = S, w = useWorkflow(C), T = w.data?.workspaceId, E = useWorkspace(T), D = useChildWorkflows(C), O;
20
+ y[2] === D.data ? O = y[3] : (O = D.data ?? [], y[2] = D.data, y[3] = O);
21
+ let k = O, A = useWorkflowConfigByName(w.data?.className ?? void 0), j;
22
+ y[4] === b ? j = y[5] : (j = b.getDashboard(), y[4] = b, y[5] = j);
23
+ let M;
24
+ y[6] === Symbol.for("react.memo_cache_sentinel") ? (M = /* @__PURE__ */ jsx(Home, { className: "h-4 w-4" }), y[6] = M) : M = y[6];
25
+ let N;
26
+ y[7] === j ? N = y[8] : (N = {
27
+ label: "Dashboard",
28
+ href: j,
29
+ icon: M
30
+ }, y[7] = j, y[8] = N);
31
+ let P;
32
+ y[9] === b ? P = y[10] : (P = b.getWorkspaces(), y[9] = b, y[10] = P);
33
+ let F;
34
+ y[11] === P ? F = y[12] : (F = {
35
+ label: "Workspaces",
36
+ href: P
37
+ }, y[11] = P, y[12] = F);
38
+ let I = E.data?.title ?? "...", L;
39
+ y[13] !== b || y[14] !== T ? (L = T ? b.getWorkspace(T) : void 0, y[13] = b, y[14] = T, y[15] = L) : L = y[15];
40
+ let R;
41
+ y[16] !== I || y[17] !== L ? (R = {
42
+ label: I,
43
+ href: L
44
+ }, y[16] = I, y[17] = L, y[18] = R) : R = y[18];
45
+ let z = `Run #${w.data?.run ?? "..."}`, B;
46
+ y[19] !== b || y[20] !== C ? (B = b.getWorkflow(C), y[19] = b, y[20] = C, y[21] = B) : B = y[21];
47
+ let V;
48
+ y[22] !== z || y[23] !== B ? (V = {
49
+ label: z,
50
+ href: B
51
+ }, y[22] = z, y[23] = B, y[24] = V) : V = y[24];
52
+ let H;
53
+ y[25] === Symbol.for("react.memo_cache_sentinel") ? (H = {
54
+ label: "Debug Flow",
55
+ icon: /* @__PURE__ */ jsx(Bug, { className: "h-4 w-4" })
56
+ }, y[25] = H) : H = y[25];
57
+ let U;
58
+ y[26] !== V || y[27] !== N || y[28] !== F || y[29] !== R ? (U = [
59
+ N,
60
+ F,
61
+ R,
62
+ V,
63
+ H
64
+ ], y[26] = V, y[27] = N, y[28] = F, y[29] = R, y[30] = U) : U = y[30];
65
+ let W = U;
66
+ if (w.isLoading || D.isLoading || E.isLoading) {
67
+ let n;
68
+ y[31] === Symbol.for("react.memo_cache_sentinel") ? (n = /* @__PURE__ */ jsx("div", {
69
+ className: "flex h-[calc(100vh-8rem)] items-center justify-center",
70
+ children: /* @__PURE__ */ jsx(Loader2, { className: "text-muted-foreground h-8 w-8 animate-spin" })
71
+ }), y[31] = n) : n = y[31];
72
+ let v;
73
+ return y[32] === W ? v = y[33] : (v = /* @__PURE__ */ jsx(MainLayout_default, {
74
+ breadcrumbsData: W,
75
+ children: n
76
+ }), y[32] = W, y[33] = v), v;
77
+ }
78
+ let G;
79
+ y[34] === w.error ? G = y[35] : (G = /* @__PURE__ */ jsx(ErrorSnackbar_default, { error: w.error }), y[34] = w.error, y[35] = G);
80
+ let K = w.data?.title ?? w.data?.alias ?? "Workflow", q = w.data?.run, J;
81
+ y[36] !== b || y[37] !== C ? (J = () => void b.navigateToWorkflow(C), y[36] = b, y[37] = C, y[38] = J) : J = y[38];
82
+ let Y;
83
+ y[39] !== K || y[40] !== q || y[41] !== J ? (Y = /* @__PURE__ */ jsx(WorkflowDebugHeader_default, {
84
+ title: K,
85
+ runNumber: q,
86
+ onBack: J
87
+ }), y[39] = K, y[40] = q, y[41] = J, y[42] = Y) : Y = y[42];
88
+ let X;
89
+ y[43] !== k || y[44] !== A || y[45] !== C ? (X = /* @__PURE__ */ jsx("div", {
90
+ className: "bg-card border-border flex-1 overflow-hidden rounded-2xl border shadow-sm",
91
+ children: k.length > 0 ? /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(WorkflowFlowViewer_default, {
92
+ workflowId: C,
93
+ workflows: k,
94
+ workflowConfig: A.data
95
+ }) }) : /* @__PURE__ */ jsx("div", {
96
+ className: "text-muted-foreground flex h-full items-center justify-center",
97
+ children: /* @__PURE__ */ jsx("p", {
98
+ className: "font-medium",
99
+ children: "No child workflows found for this workflow"
100
+ })
101
+ })
102
+ }), y[43] = k, y[44] = A, y[45] = C, y[46] = X) : X = y[46];
103
+ let Z;
104
+ y[47] !== Y || y[48] !== X ? (Z = /* @__PURE__ */ jsxs("div", {
105
+ className: "flex h-[calc(100vh-8rem)] flex-col gap-6",
106
+ children: [Y, X]
107
+ }), y[47] = Y, y[48] = X, y[49] = Z) : Z = y[49];
108
+ let Q;
109
+ return y[50] !== W || y[51] !== G || y[52] !== Z ? (Q = /* @__PURE__ */ jsxs(MainLayout_default, {
110
+ breadcrumbsData: W,
111
+ children: [G, Z]
112
+ }), y[50] = W, y[51] = G, y[52] = Z, y[53] = Q) : Q = y[53], Q;
113
+ };
114
+ export { WorkflowDebugPage_default as default };
@@ -18,8 +18,10 @@ var WorkspacePage_default = () => {
18
18
  }
19
19
  let t;
20
20
  if (v[0] !== S.data || v[1] !== C) {
21
- let _;
22
- v[3] === C ? _ = v[4] : (_ = (t) => t.blockName === C.blockName, v[3] = C, v[4] = _), t = S.data.find(_)?.ui?.actions?.find(_temp), v[0] = S.data, v[1] = C, v[2] = t;
21
+ let g;
22
+ v[3] === C ? g = v[4] : (g = (t) => t.className === C.className, v[3] = C, v[4] = g);
23
+ let _ = S.data.find(g)?.ui;
24
+ t = (_?.widgets ?? _?.actions)?.find(_temp), v[0] = S.data, v[1] = C, v[2] = t;
23
25
  } else t = v[2];
24
26
  w = t;
25
27
  }
@@ -1,5 +1,5 @@
1
1
  import { __toESM } from "../_virtual/rolldown_runtime.js";
2
- import { getDocumentsCacheKey, getNamespacesByPipelineCacheKey, getWorkflowCacheKey, getWorkflowsByPipelineCacheKey, getWorkflowsCacheKey } from "../hooks/query-keys.js";
2
+ import { getChildWorkflowsCacheKey, getDocumentsCacheKey, getWorkflowCacheKey } from "../hooks/query-keys.js";
3
3
  import { SseClientEvents } from "../events/sse-client-events.js";
4
4
  import { eventBus } from "../services/eventEmitter.js";
5
5
  import "../services/index.js";
@@ -9,31 +9,31 @@ import { c } from "react/compiler-runtime";
9
9
  import { useEffect, useRef } from "react";
10
10
  import { QueryClient, useQueryClient } from "@tanstack/react-query";
11
11
  var import_debounce = /* @__PURE__ */ __toESM(require_debounce(), 1), DEBOUNCE_MS = 300;
12
- function createDebouncedInvalidator(e, l) {
12
+ function createDebouncedInvalidator(e, o) {
13
13
  return (0, import_debounce.default)(() => {
14
- e.invalidateQueries({ queryKey: l });
14
+ e.invalidateQueries({ queryKey: o });
15
15
  }, DEBOUNCE_MS);
16
16
  }
17
17
  function InvalidationEventsProvider() {
18
- let e = c(5), { environment: f } = useStudio(), g = useQueryClient(), v;
19
- e[0] === Symbol.for("react.memo_cache_sentinel") ? (v = /* @__PURE__ */ new Map(), e[0] = v) : v = e[0];
20
- let y = useRef(v), b, x;
21
- return e[1] !== f.id || e[2] !== g ? (b = () => {
22
- if (!f.id) return;
23
- let e = f.id, d = y.current, p = function(e) {
24
- let l = JSON.stringify(e);
25
- d.has(l) || d.set(l, createDebouncedInvalidator(g, e)), d.get(l)();
26
- }, m = eventBus.on(SseClientEvents.WORKFLOW_CREATED, (l) => {
27
- l.namespaceId && p(getWorkflowsCacheKey(e, l.namespaceId)), l.pipelineId && (p(getNamespacesByPipelineCacheKey(e, l.pipelineId)), p(getWorkflowsByPipelineCacheKey(e, l.pipelineId)));
28
- }), h = eventBus.on(SseClientEvents.WORKFLOW_UPDATED, (l) => {
29
- l.id && p(getWorkflowCacheKey(e, l.id)), l.namespaceId && p(getWorkflowsCacheKey(e, l.namespaceId)), l.pipelineId && (p(getNamespacesByPipelineCacheKey(e, l.pipelineId)), p(getWorkflowsByPipelineCacheKey(e, l.pipelineId)));
30
- }), _ = eventBus.on(SseClientEvents.DOCUMENT_CREATED, (u) => {
31
- u.workflowId && p(getDocumentsCacheKey(e, u.workflowId));
18
+ let e = c(5), { environment: u } = useStudio(), m = useQueryClient(), g;
19
+ e[0] === Symbol.for("react.memo_cache_sentinel") ? (g = /* @__PURE__ */ new Map(), e[0] = g) : g = e[0];
20
+ let _ = useRef(g), v, y;
21
+ return e[1] !== u.id || e[2] !== m ? (v = () => {
22
+ if (!u.id) return;
23
+ let e = u.id, l = _.current, d = function(e) {
24
+ let o = JSON.stringify(e);
25
+ l.has(o) || l.set(o, createDebouncedInvalidator(m, e)), l.get(o)();
26
+ }, f = eventBus.on(SseClientEvents.WORKFLOW_CREATED, (s) => {
27
+ s.parentId && d(getChildWorkflowsCacheKey(e, s.parentId));
28
+ }), p = eventBus.on(SseClientEvents.WORKFLOW_UPDATED, (s) => {
29
+ s.id && d(getWorkflowCacheKey(e, s.id)), s.parentId && d(getChildWorkflowsCacheKey(e, s.parentId));
30
+ }), h = eventBus.on(SseClientEvents.DOCUMENT_CREATED, (o) => {
31
+ o.workflowId && d(getDocumentsCacheKey(e, o.workflowId));
32
32
  });
33
33
  return () => {
34
- m(), h(), _(), d.forEach(_temp), d.clear();
34
+ f(), p(), h(), l.forEach(_temp), l.clear();
35
35
  };
36
- }, x = [g, f.id], e[1] = f.id, e[2] = g, e[3] = b, e[4] = x) : (b = e[3], x = e[4]), useEffect(b, x), null;
36
+ }, y = [m, u.id], e[1] = u.id, e[2] = m, e[3] = v, e[4] = y) : (v = e[3], y = e[4]), useEffect(v, y), null;
37
37
  }
38
38
  function _temp(e) {
39
39
  return e.cancel();
@@ -16,7 +16,6 @@ function SseProvider() {
16
16
  "workflow.created",
17
17
  "workflow.updated",
18
18
  "document.created",
19
- "pipeline.updated",
20
19
  "workspace.updated"
21
20
  ].forEach((a) => {
22
21
  o.addEventListener(a, (o) => {
@@ -49,23 +49,20 @@ var LocalRouter = class {
49
49
  async navigateToWorkspace(e) {
50
50
  await this.navigate(this.getWorkspace(e));
51
51
  }
52
- getPipeline(e) {
53
- return `/pipelines/${e}`;
52
+ getWorkflow(e) {
53
+ return `/workflows/${e}`;
54
54
  }
55
- async navigateToPipeline(e) {
56
- await this.navigate(this.getPipeline(e));
55
+ async navigateToWorkflow(e) {
56
+ await this.navigate(this.getWorkflow(e));
57
57
  }
58
- getPipelineDebug(e) {
59
- return `/pipelines/${e}/debug`;
58
+ getWorkflowDebug(e) {
59
+ return `/workflows/${e}/debug`;
60
60
  }
61
- async navigateToPipelineDebug(e) {
62
- await this.navigate(this.getPipelineDebug(e));
61
+ async navigateToWorkflowDebug(e) {
62
+ await this.navigate(this.getWorkflowDebug(e));
63
63
  }
64
- async navigateToWorkflow(e, t, n) {
65
- await this.navigate(`/pipelines/${e}/workflows/${t}/${(n ? parseInt(n) : 0) + 1}`);
66
- }
67
- async navigateToPipelineNamespace(e, t, n) {
68
- await this.navigate(`/workspaces/${e}/pipelines/${t}/namespaces/${n}`);
64
+ async navigateToChildWorkflow(e, t) {
65
+ await this.navigate(`/workflows/${e}/${(t ? parseInt(t) : 0) + 1}`);
69
66
  }
70
67
  getWorkspaceRuns(e) {
71
68
  return `/workspaces/${e}/runs`;
@@ -73,11 +70,11 @@ var LocalRouter = class {
73
70
  async navigateToWorkspaceRuns(e) {
74
71
  await this.navigate(this.getWorkspaceRuns(e));
75
72
  }
76
- getEmbedPipeline(e) {
77
- return `${this.embedPrefix}/pipelines/${e}`;
73
+ getEmbedWorkflow(e) {
74
+ return `${this.embedPrefix}/workflows/${e}`;
78
75
  }
79
- getPreviewPipeline(e) {
80
- return `${this.embedPrefix}/preview/pipelines/${e}`;
76
+ getPreviewWorkflow(e) {
77
+ return `${this.embedPrefix}/preview/workflows/${e}`;
81
78
  }
82
79
  getCurrentEnvironmentId() {
83
80
  return this.envId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loopstack/loopstack-studio",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "repository": "loopstack-ai/loopstack-studio",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -26,7 +26,7 @@
26
26
  "dependencies": {
27
27
  "@fontsource/roboto": "^5.2.10",
28
28
  "@hookform/resolvers": "^5.2.2",
29
- "@loopstack/contracts": "^0.24.0",
29
+ "@loopstack/contracts": "^0.25.0",
30
30
  "@radix-ui/react-accordion": "^1.2.12",
31
31
  "@radix-ui/react-alert-dialog": "^1.1.15",
32
32
  "@radix-ui/react-avatar": "^1.1.11",
@@ -1,7 +0,0 @@
1
- function createNamespacesApi(e) {
2
- return {
3
- getById: (t) => e.get(`/api/v1/namespaces/${t.id}`).then((e) => e.data),
4
- getAll: (t) => e.get("/api/v1/namespaces", { params: t }).then((e) => e.data)
5
- };
6
- }
7
- export { createNamespacesApi };
@@ -1,13 +0,0 @@
1
- function createPipelinesApi(e) {
2
- return {
3
- getById: (t) => e.get(`/api/v1/pipelines/${t.id}`).then((e) => e.data),
4
- getAll: (t) => e.get("/api/v1/pipelines", { params: t }).then((e) => e.data),
5
- create: (t) => e.post("/api/v1/pipelines", t.pipelineCreateDto).then((e) => e.data),
6
- update: (t) => e.put(`/api/v1/pipelines/${t.id}`, t.pipelineUpdateDto).then((e) => e.data),
7
- delete: (t) => e.delete(`/api/v1/pipelines/id/${t.id}`).then((e) => e.data),
8
- batchDelete: (t) => e.delete("/api/v1/pipelines/batch", { data: { ids: t.ids } }).then((e) => e.data),
9
- getFileTree: (t) => e.get(`/api/v1/pipelines/${t.pipelineId}/files`).then((e) => e.data),
10
- getFileContent: (t) => e.get(`/api/v1/pipelines/${t.pipelineId}/files/${t.filePath}`).then((e) => e.data)
11
- };
12
- }
13
- export { createPipelinesApi };
@@ -1,158 +0,0 @@
1
- "use client";
2
- import { cn } from "../../lib/utils.js";
3
- import { Badge } from "../ui/badge.js";
4
- import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../ui/collapsible.js";
5
- import { CodeBlock } from "./code-block.js";
6
- import { c } from "react/compiler-runtime";
7
- import { isValidElement } from "react";
8
- import { jsx, jsxs } from "react/jsx-runtime";
9
- import { CheckCircleIcon, ChevronDownIcon, CircleIcon, ClockIcon, WrenchIcon, XCircleIcon } from "lucide-react";
10
- const Tool = (r) => {
11
- let a = c(8), o, s;
12
- a[0] === r ? (o = a[1], s = a[2]) : ({className: o, ...s} = r, a[0] = r, a[1] = o, a[2] = s);
13
- let l;
14
- a[3] === o ? l = a[4] : (l = cn("not-prose mb-4 w-full rounded-md border", o), a[3] = o, a[4] = l);
15
- let u;
16
- return a[5] !== s || a[6] !== l ? (u = /* @__PURE__ */ jsx(Collapsible, {
17
- className: l,
18
- ...s
19
- }), a[5] = s, a[6] = l, a[7] = u) : u = a[7], u;
20
- };
21
- var getStatusBadge = (e) => {
22
- let i = {
23
- "input-streaming": "Pending",
24
- "input-available": "Running",
25
- "approval-requested": "Awaiting Approval",
26
- "approval-responded": "Responded",
27
- "output-available": "Completed",
28
- "output-error": "Error",
29
- "output-denied": "Denied"
30
- };
31
- return /* @__PURE__ */ jsxs(Badge, {
32
- className: "gap-1.5 rounded-full text-xs",
33
- variant: "secondary",
34
- children: [{
35
- "input-streaming": /* @__PURE__ */ jsx(CircleIcon, { className: "size-4" }),
36
- "input-available": /* @__PURE__ */ jsx(ClockIcon, { className: "size-4 animate-pulse" }),
37
- "approval-requested": /* @__PURE__ */ jsx(ClockIcon, { className: "size-4 text-yellow-600" }),
38
- "approval-responded": /* @__PURE__ */ jsx(CheckCircleIcon, { className: "size-4 text-blue-600" }),
39
- "output-available": /* @__PURE__ */ jsx(CheckCircleIcon, { className: "size-4 text-green-600" }),
40
- "output-error": /* @__PURE__ */ jsx(XCircleIcon, { className: "size-4 text-red-600" }),
41
- "output-denied": /* @__PURE__ */ jsx(XCircleIcon, { className: "size-4 text-orange-600" })
42
- }[e], i[e]]
43
- });
44
- };
45
- const ToolHeader = (r) => {
46
- let i = c(24), a, s, l, d, p;
47
- i[0] === r ? (a = i[1], s = i[2], l = i[3], d = i[4], p = i[5]) : ({className: a, title: d, type: p, state: l, ...s} = r, i[0] = r, i[1] = a, i[2] = s, i[3] = l, i[4] = d, i[5] = p);
48
- let m;
49
- i[6] === a ? m = i[7] : (m = cn("flex w-full items-center justify-between gap-4 p-3", a), i[6] = a, i[7] = m);
50
- let g;
51
- i[8] === Symbol.for("react.memo_cache_sentinel") ? (g = /* @__PURE__ */ jsx(WrenchIcon, { className: "text-muted-foreground size-4" }), i[8] = g) : g = i[8];
52
- let _;
53
- i[9] !== d || i[10] !== p ? (_ = d ?? p.split("-").slice(1).join("-"), i[9] = d, i[10] = p, i[11] = _) : _ = i[11];
54
- let y;
55
- i[12] === _ ? y = i[13] : (y = /* @__PURE__ */ jsx("span", {
56
- className: "text-sm font-medium",
57
- children: _
58
- }), i[12] = _, i[13] = y);
59
- let b;
60
- i[14] === l ? b = i[15] : (b = getStatusBadge(l), i[14] = l, i[15] = b);
61
- let x;
62
- i[16] !== y || i[17] !== b ? (x = /* @__PURE__ */ jsxs("div", {
63
- className: "flex items-center gap-2",
64
- children: [
65
- g,
66
- y,
67
- b
68
- ]
69
- }), i[16] = y, i[17] = b, i[18] = x) : x = i[18];
70
- let S;
71
- i[19] === Symbol.for("react.memo_cache_sentinel") ? (S = /* @__PURE__ */ jsx(ChevronDownIcon, { className: "text-muted-foreground size-4 transition-transform group-data-[state=open]:rotate-180" }), i[19] = S) : S = i[19];
72
- let C;
73
- return i[20] !== s || i[21] !== m || i[22] !== x ? (C = /* @__PURE__ */ jsxs(CollapsibleTrigger, {
74
- className: m,
75
- ...s,
76
- children: [x, S]
77
- }), i[20] = s, i[21] = m, i[22] = x, i[23] = C) : C = i[23], C;
78
- }, ToolContent = (r) => {
79
- let i = c(8), o, s;
80
- i[0] === r ? (o = i[1], s = i[2]) : ({className: o, ...s} = r, i[0] = r, i[1] = o, i[2] = s);
81
- let l;
82
- i[3] === o ? l = i[4] : (l = cn("data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-popover-foreground data-[state=closed]:animate-out data-[state=open]:animate-in outline-none", o), i[3] = o, i[4] = l);
83
- let u;
84
- return i[5] !== s || i[6] !== l ? (u = /* @__PURE__ */ jsx(CollapsibleContent, {
85
- className: l,
86
- ...s
87
- }), i[5] = s, i[6] = l, i[7] = u) : u = i[7], u;
88
- }, ToolInput = (r) => {
89
- let i = c(15), a, o, l;
90
- i[0] === r ? (a = i[1], o = i[2], l = i[3]) : ({className: a, input: o, ...l} = r, i[0] = r, i[1] = a, i[2] = o, i[3] = l);
91
- let d;
92
- i[4] === a ? d = i[5] : (d = cn("space-y-2 overflow-hidden p-4", a), i[4] = a, i[5] = d);
93
- let f;
94
- i[6] === Symbol.for("react.memo_cache_sentinel") ? (f = /* @__PURE__ */ jsx("h4", {
95
- className: "text-muted-foreground text-xs font-medium tracking-wide uppercase",
96
- children: "Parameters"
97
- }), i[6] = f) : f = i[6];
98
- let p;
99
- i[7] === o ? p = i[8] : (p = JSON.stringify(o, null, 2), i[7] = o, i[8] = p);
100
- let m;
101
- i[9] === p ? m = i[10] : (m = /* @__PURE__ */ jsx("div", {
102
- className: "bg-muted/50 rounded-md",
103
- children: /* @__PURE__ */ jsx(CodeBlock, {
104
- code: p,
105
- language: "json"
106
- })
107
- }), i[9] = p, i[10] = m);
108
- let h;
109
- return i[11] !== l || i[12] !== d || i[13] !== m ? (h = /* @__PURE__ */ jsxs("div", {
110
- className: d,
111
- ...l,
112
- children: [f, m]
113
- }), i[11] = l, i[12] = d, i[13] = m, i[14] = h) : h = i[14], h;
114
- }, ToolOutput = (r) => {
115
- let i = c(30), a, o, d, f;
116
- if (i[0] === r ? (a = i[1], o = i[2], d = i[3], f = i[4]) : ({className: a, output: d, errorText: o, ...f} = r, i[0] = r, i[1] = a, i[2] = o, i[3] = d, i[4] = f), !(d || o)) return null;
117
- let p = d, m;
118
- i[5] === p ? m = i[6] : (m = /* @__PURE__ */ jsx("div", { children: p }), i[5] = p, i[6] = m);
119
- let h = m;
120
- if (typeof d == "object" && !isValidElement(d)) {
121
- let e;
122
- i[7] === d ? e = i[8] : (e = JSON.stringify(d, null, 2), i[7] = d, i[8] = e);
123
- let r;
124
- i[9] === e ? r = i[10] : (r = /* @__PURE__ */ jsx(CodeBlock, {
125
- code: e,
126
- language: "json"
127
- }), i[9] = e, i[10] = r), h = r;
128
- } else if (typeof d == "string") {
129
- let e;
130
- i[11] === d ? e = i[12] : (e = /* @__PURE__ */ jsx(CodeBlock, {
131
- code: d,
132
- language: "json"
133
- }), i[11] = d, i[12] = e), h = e;
134
- }
135
- let g;
136
- i[13] === a ? g = i[14] : (g = cn("space-y-2 p-4", a), i[13] = a, i[14] = g);
137
- let _ = o ? "Error" : "Result", v;
138
- i[15] === _ ? v = i[16] : (v = /* @__PURE__ */ jsx("h4", {
139
- className: "text-muted-foreground text-xs font-medium tracking-wide uppercase",
140
- children: _
141
- }), i[15] = _, i[16] = v);
142
- let y = o ? "bg-destructive/10 text-destructive" : "bg-muted/50 text-foreground", b;
143
- i[17] === y ? b = i[18] : (b = cn("overflow-x-auto rounded-md text-xs [&_table]:w-full", y), i[17] = y, i[18] = b);
144
- let x;
145
- i[19] === o ? x = i[20] : (x = o && /* @__PURE__ */ jsx("div", { children: o }), i[19] = o, i[20] = x);
146
- let S;
147
- i[21] !== h || i[22] !== b || i[23] !== x ? (S = /* @__PURE__ */ jsxs("div", {
148
- className: b,
149
- children: [x, h]
150
- }), i[21] = h, i[22] = b, i[23] = x, i[24] = S) : S = i[24];
151
- let C;
152
- return i[25] !== f || i[26] !== g || i[27] !== v || i[28] !== S ? (C = /* @__PURE__ */ jsxs("div", {
153
- className: g,
154
- ...f,
155
- children: [v, S]
156
- }), i[25] = f, i[26] = g, i[27] = v, i[28] = S, i[29] = C) : C = i[29], C;
157
- };
158
- export { Tool, ToolContent, ToolHeader, ToolInput, ToolOutput };
@@ -1,42 +0,0 @@
1
- import { Button } from "../../ui/button.js";
2
- import { useUpsertSecret } from "../../../hooks/useSecrets.js";
3
- import { useWorkbenchLayout } from "../../../features/workbench/providers/WorkbenchLayoutProvider.js";
4
- import "../../../features/workbench/index.js";
5
- import React, { useState } from "react";
6
- import { jsx, jsxs } from "react/jsx-runtime";
7
- import { Info, KeyRound, Loader2 } from "lucide-react";
8
- import { useFormContext } from "react-hook-form";
9
- const SecretInput = ({ ui: u, disabled: d, onSubmit: f }) => {
10
- let { pipeline: p } = useWorkbenchLayout(), m = p?.workspaceId, h = useFormContext(), g = useUpsertSecret(), [_, v] = useState(!1), y = async () => {
11
- if (m) {
12
- v(!0);
13
- try {
14
- let e = h.getValues().variables ?? [], c = [];
15
- for (let l of e) !l.key?.trim() || !l.value?.trim() || (await g.mutateAsync({
16
- workspaceId: m,
17
- key: l.key,
18
- value: l.value
19
- }), c.push(l.key));
20
- f({ keys: c });
21
- } finally {
22
- v(!1);
23
- }
24
- }
25
- };
26
- return /* @__PURE__ */ jsxs("div", {
27
- className: "flex w-full flex-col gap-3",
28
- children: [/* @__PURE__ */ jsxs("div", {
29
- className: "text-muted-foreground flex items-center gap-2 text-xs",
30
- children: [/* @__PURE__ */ jsx(Info, { className: "h-3.5 w-3.5 shrink-0" }), /* @__PURE__ */ jsx("span", { children: "To add or remove other secrets, use the Secrets panel in the right sidebar." })]
31
- }), /* @__PURE__ */ jsx("div", {
32
- className: "flex justify-end",
33
- children: /* @__PURE__ */ jsxs(Button, {
34
- onClick: () => void y(),
35
- disabled: d || _,
36
- className: "w-48",
37
- children: [_ ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(KeyRound, { className: "mr-2 h-4 w-4" }), u?.label ?? "Save & Continue"]
38
- })
39
- })]
40
- });
41
- };
42
- export { SecretInput };