@loopstack/loopstack-studio 0.21.3 → 0.23.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 (126) hide show
  1. package/dist/api/auth.js +10 -0
  2. package/dist/api/client.js +13 -0
  3. package/dist/api/config.js +10 -0
  4. package/dist/api/dashboard.js +4 -0
  5. package/dist/api/documents.js +7 -0
  6. package/dist/api/index.js +24 -0
  7. package/dist/api/namespaces.js +7 -0
  8. package/dist/api/pipelines.js +13 -0
  9. package/dist/api/processor.js +4 -0
  10. package/dist/api/workflows.js +8 -0
  11. package/dist/api/workspaces.js +12 -0
  12. package/dist/app/EnvironmentEmbedRoot.js +35 -0
  13. package/dist/components/data-table/DataTableFilters.js +74 -63
  14. package/dist/components/feedback/ErrorBoundary.js +43 -0
  15. package/dist/components/{LoadingCentered.js → feedback/LoadingCentered.js} +1 -1
  16. package/dist/components/feedback/index.js +5 -0
  17. package/dist/components/index.js +6 -3
  18. package/dist/components/layout/MainLayout.js +36 -17
  19. package/dist/components/layout/StudioSidebar.js +165 -0
  20. package/dist/components/page/PageBreadcrumbs.js +1 -1
  21. package/dist/components/ui/sidebar.js +359 -359
  22. package/dist/components/ui-widgets/UiActions.js +22 -15
  23. package/dist/components/ui-widgets/UiWidget.js +31 -26
  24. package/dist/components/ui-widgets/widgets/AiPromptInput.js +27 -27
  25. package/dist/components/ui-widgets/widgets/ButtonFullWidth.js +12 -12
  26. package/dist/components/ui-widgets/widgets/SandboxRun.js +33 -0
  27. package/dist/components/ui-widgets/widgets/SubmitButton.js +11 -11
  28. package/dist/features/code-explorer/CodeExplorer.js +4 -67
  29. package/dist/features/code-explorer/components/CodeExplorerTree.js +3 -41
  30. package/dist/features/code-explorer/components/CodeExplorerTreeNode.js +4 -80
  31. package/dist/features/code-explorer/components/FileContentViewer.js +1 -0
  32. package/dist/features/code-explorer/components/FileTabsBar.js +1 -1
  33. package/dist/features/code-explorer/index.js +4 -0
  34. package/dist/features/code-explorer/utils/fileIcons.js +4 -7
  35. package/dist/features/debug/components/ConfigFlowViewer.js +1 -1
  36. package/dist/features/debug/components/PipelineFlowViewer.js +1 -1
  37. package/dist/features/debug/index.js +3 -0
  38. package/dist/features/documents/DocumentRenderer.js +53 -0
  39. package/dist/features/{workbench → documents}/components/DocumentItem.js +1 -1
  40. package/dist/features/documents/components/DocumentList.js +40 -0
  41. package/dist/features/{workbench → documents}/components/DocumentMetadataPills.js +2 -2
  42. package/dist/features/{workbench/components → documents}/document-details/DocumentDetails.js +3 -3
  43. package/dist/features/{workbench/components → documents}/document-details/PromptDetails.js +3 -3
  44. package/dist/features/documents/index.js +4 -0
  45. package/dist/features/{workbench/components/document-renderer → documents/renderers}/AiMessage.js +5 -5
  46. package/dist/features/{workbench/components/document-renderer → documents/renderers}/DocumentDebugRenderer.js +1 -1
  47. package/dist/features/{workbench/components/document-renderer → documents/renderers}/DocumentFormRenderer.js +9 -8
  48. package/dist/features/{workbench/components/document-renderer → documents/renderers}/DocumentMessageRenderer.js +1 -1
  49. package/dist/features/{workbench/components/document-renderer → documents/renderers}/ErrorMessageRenderer.js +1 -1
  50. package/dist/features/{workbench/components/document-renderer → documents/renderers}/LinkMessageRenderer.js +1 -1
  51. package/dist/features/{workbench/components/document-renderer → documents/renderers}/MarkdownMessageRenderer.js +2 -2
  52. package/dist/features/{workbench/components/document-renderer → documents/renderers}/PlainMessageRenderer.js +1 -1
  53. package/dist/features/health/index.js +1 -0
  54. package/dist/features/oauth/OAuthPromptRenderer.js +1 -1
  55. package/dist/features/runs/Runs.js +197 -0
  56. package/dist/features/workbench/NavigationItems.js +29 -29
  57. package/dist/features/workbench/Workbench.js +100 -78
  58. package/dist/features/workbench/WorkflowItem.js +63 -58
  59. package/dist/features/workbench/WorkflowList.js +62 -82
  60. package/dist/features/workbench/components/NewRunDialog.js +329 -0
  61. package/dist/features/workbench/components/WorkbenchFloatingPanel.js +88 -0
  62. package/dist/features/workbench/components/WorkbenchFlowPanel.js +49 -0
  63. package/dist/features/workbench/components/WorkbenchIconSidebar.js +68 -0
  64. package/dist/features/workbench/components/WorkbenchPreviewPanel.js +128 -0
  65. package/dist/features/workbench/components/WorkflowForms.js +7 -6
  66. package/dist/features/workbench/components/WorkflowHistoryItem.js +74 -69
  67. package/dist/features/workbench/components/buttons/WorkflowButtons.js +78 -61
  68. package/dist/features/workbench/hooks/useWorkflowData.js +49 -0
  69. package/dist/features/workbench/hooks/useWorkflowListState.js +50 -0
  70. package/dist/features/workbench/index.js +8 -0
  71. package/dist/features/workbench/providers/WorkbenchLayoutProvider.js +76 -0
  72. package/dist/features/workspaces/Workspaces.js +2 -2
  73. package/dist/features/workspaces/components/CreateWorkspace.js +165 -82
  74. package/dist/features/workspaces/components/EnvironmentSlotSelector.js +63 -0
  75. package/dist/features/workspaces/components/ExecutionTimeline.js +70 -69
  76. package/dist/features/workspaces/components/PipelineForm.js +4 -4
  77. package/dist/features/workspaces/index.js +3 -0
  78. package/dist/hooks/index.js +3 -0
  79. package/dist/hooks/query-keys.js +138 -0
  80. package/dist/hooks/useApi.js +9 -33
  81. package/dist/hooks/useAuth.js +37 -56
  82. package/dist/hooks/useConfig.js +27 -33
  83. package/dist/hooks/useDashboard.js +9 -16
  84. package/dist/hooks/useDebounce.js +8 -17
  85. package/dist/hooks/useDocuments.js +7 -16
  86. package/dist/hooks/useFiles.js +24 -42
  87. package/dist/hooks/useNamespaces.js +7 -16
  88. package/dist/hooks/usePipelines.js +141 -174
  89. package/dist/hooks/useProcessor.js +11 -17
  90. package/dist/hooks/useWorkflows.js +51 -89
  91. package/dist/hooks/useWorkspaces.js +97 -129
  92. package/dist/index.d.ts +364 -50
  93. package/dist/index.js +21 -6
  94. package/dist/packages/contracts/dist/enums/index.js +25 -0
  95. package/dist/packages/contracts/dist/enums/pipeline-state.js +10 -0
  96. package/dist/packages/contracts/dist/enums/registry.enum.js +20 -0
  97. package/dist/packages/contracts/dist/enums/sort-order.enum.js +10 -0
  98. package/dist/packages/contracts/dist/enums/user-type.enum.js +10 -0
  99. package/dist/packages/contracts/dist/enums/workflow-state.enum.js +10 -0
  100. package/dist/pages/DashboardPage.js +1 -1
  101. package/dist/pages/DebugPage.js +12 -14
  102. package/dist/pages/DebugWorkflowDetailsPage.js +2 -2
  103. package/dist/pages/DebugWorkflowsPage.js +3 -4
  104. package/dist/pages/EmbedWorkbenchPage.js +7 -5
  105. package/dist/pages/PipelineDebugPage.js +7 -6
  106. package/dist/pages/PreviewWorkbenchPage.js +419 -0
  107. package/dist/pages/RunsListPage.js +64 -0
  108. package/dist/pages/RunsPage.js +49 -0
  109. package/dist/pages/StudioLandingPage.js +146 -0
  110. package/dist/pages/WorkbenchPage.js +78 -53
  111. package/dist/pages/WorkspacePage.js +1 -1
  112. package/dist/providers/InvalidationEventsProvider.js +15 -17
  113. package/dist/providers/QueryProvider.js +21 -0
  114. package/dist/providers/StudioProvider.js +2 -2
  115. package/dist/routing/LocalRouter.js +20 -7
  116. package/dist/services/createApiClient.js +4 -10
  117. package/dist/services/index.js +1 -1
  118. package/package.json +2 -3
  119. package/dist/features/workbench/components/DocumentList.js +0 -40
  120. package/dist/features/workbench/components/DocumentRenderer.js +0 -54
  121. package/dist/features/workbench/components/WorkbenchSidebar.js +0 -109
  122. package/dist/features/workbench/providers/WorkbenchContextProvider.js +0 -3
  123. /package/dist/components/{content → feedback}/ErrorAlert.js +0 -0
  124. /package/dist/components/{snackbars → feedback}/ErrorSnackbar.js +0 -0
  125. /package/dist/components/{snackbars → feedback}/Snackbar.js +0 -0
  126. /package/dist/features/{workbench/components/document-renderer → documents/renderers}/AiMessageContent.js +0 -0
@@ -0,0 +1,64 @@
1
+ import { useStudio } from "../providers/StudioProvider.js";
2
+ import { Button } from "../components/ui/button.js";
3
+ import MainLayout_default from "../components/layout/MainLayout.js";
4
+ import { NewRunDialog } from "../features/workbench/components/NewRunDialog.js";
5
+ import Runs_default from "../features/runs/Runs.js";
6
+ import { c } from "react/compiler-runtime";
7
+ import { useState } from "react";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { Home, Play } from "lucide-react";
10
+ function RunsListPage() {
11
+ let f = c(19), { router: p } = useStudio(), [m, h] = useState(!1), g;
12
+ f[0] === p ? g = f[1] : (g = p.getDashboard(), f[0] = p, f[1] = g);
13
+ let _;
14
+ f[2] === Symbol.for("react.memo_cache_sentinel") ? (_ = /* @__PURE__ */ jsx(Home, { className: "h-4 w-4" }), f[2] = _) : _ = f[2];
15
+ let v;
16
+ f[3] === g ? v = f[4] : (v = {
17
+ label: "Dashboard",
18
+ href: g,
19
+ icon: _
20
+ }, f[3] = g, f[4] = v);
21
+ let y;
22
+ f[5] === Symbol.for("react.memo_cache_sentinel") ? (y = {
23
+ label: "Runs",
24
+ current: !0
25
+ }, f[5] = y) : y = f[5];
26
+ let b;
27
+ f[6] === v ? b = f[7] : (b = [v, y], f[6] = v, f[7] = b);
28
+ let x = b, S;
29
+ f[8] === Symbol.for("react.memo_cache_sentinel") ? (S = /* @__PURE__ */ jsx("h1", {
30
+ className: "text-3xl font-bold tracking-tight",
31
+ children: "Runs"
32
+ }), f[8] = S) : S = f[8];
33
+ let C, w;
34
+ f[9] === Symbol.for("react.memo_cache_sentinel") ? (C = /* @__PURE__ */ jsxs("div", {
35
+ className: "mb-4 flex items-center justify-between",
36
+ children: [S, /* @__PURE__ */ jsxs(Button, {
37
+ variant: "default",
38
+ size: "sm",
39
+ className: "gap-1.5",
40
+ onClick: () => h(!0),
41
+ children: [/* @__PURE__ */ jsx(Play, { className: "h-3.5 w-3.5" }), "New Run"]
42
+ })]
43
+ }), w = /* @__PURE__ */ jsx(Runs_default, {}), f[9] = C, f[10] = w) : (C = f[9], w = f[10]);
44
+ let T;
45
+ f[11] === p ? T = f[12] : (T = (r) => {
46
+ h(!1), p.navigateToPipeline(r);
47
+ }, f[11] = p, f[12] = T);
48
+ let E;
49
+ f[13] !== m || f[14] !== T ? (E = /* @__PURE__ */ jsx(NewRunDialog, {
50
+ open: m,
51
+ onOpenChange: h,
52
+ onSuccess: T
53
+ }), f[13] = m, f[14] = T, f[15] = E) : E = f[15];
54
+ let D;
55
+ return f[16] !== x || f[17] !== E ? (D = /* @__PURE__ */ jsxs(MainLayout_default, {
56
+ breadcrumbsData: x,
57
+ children: [
58
+ C,
59
+ w,
60
+ E
61
+ ]
62
+ }), f[16] = x, f[17] = E, f[18] = D) : D = f[18], D;
63
+ }
64
+ export { RunsListPage as default };
@@ -0,0 +1,49 @@
1
+ import { useStudio } from "../providers/StudioProvider.js";
2
+ import MainLayout_default from "../components/layout/MainLayout.js";
3
+ import Runs_default from "../features/runs/Runs.js";
4
+ import { c } from "react/compiler-runtime";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { Home } from "lucide-react";
7
+ function RunsPage() {
8
+ let s = c(17), { router: l } = useStudio(), u;
9
+ s[0] === l ? u = s[1] : (u = l.getDashboard(), s[0] = l, s[1] = u);
10
+ let d;
11
+ s[2] === Symbol.for("react.memo_cache_sentinel") ? (d = /* @__PURE__ */ jsx(Home, { className: "h-4 w-4" }), s[2] = d) : d = s[2];
12
+ let f;
13
+ s[3] === u ? f = s[4] : (f = {
14
+ label: "Dashboard",
15
+ href: u,
16
+ icon: d
17
+ }, s[3] = u, s[4] = f);
18
+ let p;
19
+ s[5] === l ? p = s[6] : (p = l.getRuns(), s[5] = l, s[6] = p);
20
+ let m;
21
+ s[7] === p ? m = s[8] : (m = {
22
+ label: "Runs",
23
+ href: p
24
+ }, s[7] = p, s[8] = m);
25
+ let h;
26
+ s[9] === Symbol.for("react.memo_cache_sentinel") ? (h = {
27
+ label: "Action Required",
28
+ current: !0
29
+ }, s[9] = h) : h = s[9];
30
+ let g;
31
+ s[10] !== f || s[11] !== m ? (g = [
32
+ f,
33
+ m,
34
+ h
35
+ ], s[10] = f, s[11] = m, s[12] = g) : g = s[12];
36
+ let _ = g, v;
37
+ s[13] === Symbol.for("react.memo_cache_sentinel") ? (v = /* @__PURE__ */ jsx("h1", {
38
+ className: "mb-4 text-3xl font-bold tracking-tight",
39
+ children: "Action Required"
40
+ }), s[13] = v) : v = s[13];
41
+ let y;
42
+ s[14] === Symbol.for("react.memo_cache_sentinel") ? (y = /* @__PURE__ */ jsx(Runs_default, { defaultFilters: { status: "paused" } }), s[14] = y) : y = s[14];
43
+ let b;
44
+ return s[15] === _ ? b = s[16] : (b = /* @__PURE__ */ jsxs(MainLayout_default, {
45
+ breadcrumbsData: _,
46
+ children: [v, y]
47
+ }), s[15] = _, s[16] = b), b;
48
+ }
49
+ export { RunsPage as default };
@@ -0,0 +1,146 @@
1
+ import { useStudio } from "../providers/StudioProvider.js";
2
+ import { useFilterPipelines } from "../hooks/usePipelines.js";
3
+ import { Button } from "../components/ui/button.js";
4
+ import { NewRunDialog } from "../features/workbench/components/NewRunDialog.js";
5
+ import "../features/workbench/index.js";
6
+ import { c } from "react/compiler-runtime";
7
+ import { useCallback, useState } from "react";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { ChevronDown, Loader2, Play } from "lucide-react";
10
+ import { formatDistanceToNow } from "date-fns";
11
+ var STATUS_DOT_COLORS = {
12
+ completed: "bg-green-500",
13
+ running: "bg-blue-500",
14
+ failed: "bg-red-500",
15
+ paused: "bg-yellow-500",
16
+ canceled: "bg-orange-500",
17
+ pending: "bg-muted-foreground"
18
+ };
19
+ function StudioLandingPage() {
20
+ let s = c(28), { router: p } = useStudio(), [m, h] = useState(!1), [v, y] = useState(3), b;
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;
23
+ s[1] === x.data?.data ? S = s[2] : (S = x.data?.data ?? [], s[1] = x.data?.data, s[2] = S);
24
+ let C = S, w = x.data?.total ?? 0, T = C.length < w, E;
25
+ s[3] === Symbol.for("react.memo_cache_sentinel") ? (E = {
26
+ parentId: null,
27
+ status: "paused"
28
+ }, s[3] = E) : E = s[3];
29
+ let D = useFilterPipelines(void 0, E, "createdAt", "DESC", 0, 5), O;
30
+ s[4] === D.data?.data ? O = s[5] : (O = D.data?.data ?? [], s[4] = D.data?.data, s[5] = O);
31
+ let k = O, A;
32
+ s[6] === p ? A = s[7] : (A = (e) => {
33
+ h(!1), p.navigateToPipeline(e);
34
+ }, s[6] = p, s[7] = A);
35
+ let j = A, M;
36
+ s[8] === p ? M = s[9] : (M = (e) => {
37
+ p.navigateToPipeline(e);
38
+ }, s[8] = p, s[9] = M);
39
+ let N = M, P;
40
+ s[10] === Symbol.for("react.memo_cache_sentinel") ? (P = /* @__PURE__ */ jsx("div", {
41
+ className: "flex justify-center",
42
+ children: /* @__PURE__ */ jsxs(Button, {
43
+ variant: "secondary",
44
+ size: "sm",
45
+ className: "gap-1.5",
46
+ onClick: () => h(!0),
47
+ children: [/* @__PURE__ */ jsx(Play, { className: "h-3.5 w-3.5" }), "New Run"]
48
+ })
49
+ }), s[10] = P) : P = s[10];
50
+ let F;
51
+ s[11] !== N || s[12] !== k ? (F = k.length > 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
52
+ className: "text-muted-foreground mb-2 text-xs font-medium",
53
+ children: "Needs Attention"
54
+ }), /* @__PURE__ */ jsx("div", {
55
+ className: "divide-border divide-y",
56
+ children: k.map((e) => /* @__PURE__ */ jsx(RecentRunItem, {
57
+ pipeline: e,
58
+ onClick: () => N(e.id)
59
+ }, e.id))
60
+ })] }), s[11] = N, s[12] = k, s[13] = F) : F = s[13];
61
+ let I;
62
+ s[14] !== x.isLoading || s[15] !== N || s[16] !== T || s[17] !== C ? (I = x.isLoading && C.length === 0 ? /* @__PURE__ */ jsx("div", {
63
+ className: "flex justify-center py-4",
64
+ children: /* @__PURE__ */ jsx(Loader2, { className: "text-muted-foreground h-4 w-4 animate-spin" })
65
+ }) : C.length > 0 ? /* @__PURE__ */ jsxs("div", { children: [
66
+ /* @__PURE__ */ jsx("p", {
67
+ className: "text-muted-foreground mb-2 text-xs font-medium",
68
+ children: "Recent"
69
+ }),
70
+ /* @__PURE__ */ jsx("div", {
71
+ className: "max-h-[280px] overflow-auto",
72
+ children: /* @__PURE__ */ jsx("div", {
73
+ className: "divide-border divide-y",
74
+ children: C.map((e) => /* @__PURE__ */ jsx(RecentRunItem, {
75
+ pipeline: e,
76
+ onClick: () => N(e.id)
77
+ }, e.id))
78
+ })
79
+ }),
80
+ T && /* @__PURE__ */ jsxs("button", {
81
+ className: "text-muted-foreground hover:text-foreground mt-2 flex w-full items-center justify-center gap-1 py-1 text-xs transition-colors",
82
+ onClick: () => y(_temp),
83
+ children: [/* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3" }), "Load more"]
84
+ })
85
+ ] }) : null, s[14] = x.isLoading, s[15] = N, s[16] = T, s[17] = C, s[18] = I) : I = s[18];
86
+ let L;
87
+ s[19] !== F || s[20] !== I ? (L = /* @__PURE__ */ jsxs("div", {
88
+ className: "w-full max-w-sm space-y-6 px-4",
89
+ children: [
90
+ P,
91
+ F,
92
+ I
93
+ ]
94
+ }), s[19] = F, s[20] = I, s[21] = L) : L = s[21];
95
+ let R;
96
+ s[22] !== j || s[23] !== m ? (R = /* @__PURE__ */ jsx(NewRunDialog, {
97
+ open: m,
98
+ onOpenChange: h,
99
+ onSuccess: j
100
+ }), s[22] = j, s[23] = m, s[24] = R) : R = s[24];
101
+ let z;
102
+ return s[25] !== R || s[26] !== L ? (z = /* @__PURE__ */ jsxs("div", {
103
+ className: "flex h-full flex-col items-center justify-center",
104
+ children: [L, R]
105
+ }), s[25] = R, s[26] = L, s[27] = z) : z = s[27], z;
106
+ }
107
+ function _temp(e) {
108
+ return e + 5;
109
+ }
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;
112
+ i[0] === s ? l = i[1] : (l = /* @__PURE__ */ jsx("span", { className: s }), i[0] = s, i[1] = l);
113
+ let u;
114
+ i[2] !== a.blockName || i[3] !== a.run ? (u = /* @__PURE__ */ jsxs("span", {
115
+ className: "truncate text-sm font-medium",
116
+ children: [
117
+ "Run #",
118
+ a.run,
119
+ " · ",
120
+ a.blockName
121
+ ]
122
+ }), i[2] = a.blockName, i[3] = a.run, i[4] = u) : u = i[4];
123
+ let d;
124
+ i[5] !== l || i[6] !== u ? (d = /* @__PURE__ */ jsxs("div", {
125
+ className: "flex items-center gap-2",
126
+ children: [l, u]
127
+ }), i[5] = l, i[6] = u, i[7] = d) : d = i[7];
128
+ let f = a.status, h;
129
+ i[8] === a.createdAt ? h = i[9] : (h = formatDistanceToNow(new Date(a.createdAt), { addSuffix: !0 }), i[8] = a.createdAt, i[9] = h);
130
+ let g;
131
+ i[10] !== a.status || i[11] !== h ? (g = /* @__PURE__ */ jsxs("p", {
132
+ className: "text-muted-foreground mt-0.5 pl-3.5 text-xs",
133
+ children: [
134
+ f,
135
+ " · ",
136
+ h
137
+ ]
138
+ }), i[10] = a.status, i[11] = h, i[12] = g) : g = i[12];
139
+ let _;
140
+ return i[13] !== o || i[14] !== d || i[15] !== g ? (_ = /* @__PURE__ */ jsxs("button", {
141
+ className: "hover:bg-accent w-full rounded-md px-2 py-2.5 text-left transition-colors",
142
+ onClick: o,
143
+ children: [d, g]
144
+ }), i[13] = o, i[14] = d, i[15] = g, i[16] = _) : _ = i[16], _;
145
+ }
146
+ export { StudioLandingPage as default };
@@ -1,67 +1,92 @@
1
1
  import { useStudio } from "../providers/StudioProvider.js";
2
- import { useWorkspace } from "../hooks/useWorkspaces.js";
3
- import MainLayout_default from "../components/layout/MainLayout.js";
4
- import ErrorSnackbar_default from "../components/snackbars/ErrorSnackbar.js";
5
- import LoadingCentered_default from "../components/LoadingCentered.js";
6
2
  import { usePipeline } from "../hooks/usePipelines.js";
3
+ import { useWorkspace } from "../hooks/useWorkspaces.js";
4
+ import LoadingCentered_default from "../components/feedback/LoadingCentered.js";
5
+ import ErrorSnackbar_default from "../components/feedback/ErrorSnackbar.js";
7
6
  import Workbench from "../features/workbench/Workbench.js";
7
+ import "../features/workbench/index.js";
8
8
  import { requireParam } from "../lib/requireParam.js";
9
9
  import { c } from "react/compiler-runtime";
10
+ import { useCallback, useMemo } from "react";
10
11
  import { jsx, jsxs } from "react/jsx-runtime";
11
12
  import { useParams } from "react-router-dom";
12
13
  import { Home } from "lucide-react";
13
- function WorkbenchPage() {
14
- let m = c(37), { router: h } = useStudio(), g = useParams(), _;
15
- m[0] === g ? _ = m[1] : (_ = requireParam(g, "pipelineId"), m[0] = g, m[1] = _);
16
- let v = usePipeline(_), y = v.data?.workspaceId, b = useWorkspace(y), x;
17
- m[2] === h ? x = m[3] : (x = h.getDashboard(), m[2] = h, m[3] = x);
18
- let S;
19
- m[4] === Symbol.for("react.memo_cache_sentinel") ? (S = /* @__PURE__ */ jsx(Home, { className: "h-4 w-4" }), m[4] = S) : S = m[4];
20
- let C;
21
- m[5] === x ? C = m[6] : (C = {
14
+ function WorkbenchPage(m) {
15
+ let h = c(45), g;
16
+ h[0] === m ? g = h[1] : (g = m === void 0 ? {} : m, h[0] = m, h[1] = g);
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);
20
+ O.data?.environments;
21
+ let k = S ?? O.data?.environments, A = x ?? _temp, j;
22
+ h[4] === C ? j = h[5] : (j = C.getDashboard(), h[4] = C, h[5] = j);
23
+ let M;
24
+ h[6] === Symbol.for("react.memo_cache_sentinel") ? (M = /* @__PURE__ */ jsx(Home, { className: "h-4 w-4" }), h[6] = M) : M = h[6];
25
+ let N;
26
+ h[7] === j ? N = h[8] : (N = {
22
27
  label: "Dashboard",
23
- href: x,
24
- icon: S
25
- }, m[5] = x, m[6] = C);
26
- let w;
27
- m[7] === h ? w = m[8] : (w = h.getWorkspaces(), m[7] = h, m[8] = w);
28
- let T;
29
- m[9] === w ? T = m[10] : (T = {
30
- label: "Workspaces",
31
- href: w
32
- }, m[9] = w, m[10] = T);
33
- let E = b.data?.title ?? "", D;
34
- m[11] !== h || m[12] !== y ? (D = y ? h.getWorkspace(y) : void 0, m[11] = h, m[12] = y, m[13] = D) : D = m[13];
35
- let O;
36
- m[14] !== E || m[15] !== D ? (O = {
37
- label: E,
38
- href: D
39
- }, m[14] = E, m[15] = D, m[16] = O) : O = m[16];
40
- let k = `Run #${v.data?.run}${v.data?.title ? ` (${v.data.title})` : ""}`, A;
41
- m[17] === k ? A = m[18] : (A = { label: k }, m[17] = k, m[18] = A);
42
- let j;
43
- m[19] !== A || m[20] !== C || m[21] !== T || m[22] !== O ? (j = [
44
- C,
45
- T,
46
- O,
47
- A
48
- ], m[19] = A, m[20] = C, m[21] = T, m[22] = O, m[23] = j) : j = m[23];
49
- let M = j, N;
50
- m[24] === v.error ? N = m[25] : (N = /* @__PURE__ */ jsx(ErrorSnackbar_default, { error: v.error }), m[24] = v.error, m[25] = N);
28
+ href: j,
29
+ icon: M
30
+ }, h[7] = j, h[8] = N);
51
31
  let P;
52
- m[26] !== v.data || m[27] !== v.error || m[28] !== v.isLoading ? (P = v.data ? /* @__PURE__ */ jsx(Workbench, { pipeline: v.data }) : !v.isLoading && !v.error ? /* @__PURE__ */ jsx("p", {
32
+ h[9] === C ? P = h[10] : (P = C.getWorkspaces(), h[9] = C, h[10] = P);
33
+ let F;
34
+ h[11] === P ? F = h[12] : (F = {
35
+ label: "Workspaces",
36
+ href: P
37
+ }, h[11] = P, h[12] = F);
38
+ let I = O.data?.title ?? "", L;
39
+ h[13] !== C || h[14] !== D ? (L = D ? C.getWorkspace(D) : void 0, h[13] = C, h[14] = D, h[15] = L) : L = h[15];
40
+ let R;
41
+ h[16] !== I || h[17] !== L ? (R = {
42
+ label: I,
43
+ href: L
44
+ }, h[16] = I, h[17] = L, h[18] = R) : R = h[18];
45
+ let z = `Run #${E.data?.run}${E.data?.title ? ` (${E.data.title})` : ""}`, B;
46
+ h[19] === z ? B = h[20] : (B = { label: z }, h[19] = z, h[20] = B);
47
+ let V;
48
+ h[21] !== R || h[22] !== B || h[23] !== N || h[24] !== F ? (V = [
49
+ N,
50
+ F,
51
+ R,
52
+ B
53
+ ], h[21] = R, h[22] = B, h[23] = N, h[24] = F, h[25] = V) : V = h[25];
54
+ let H = V, U;
55
+ h[26] === E.error ? U = h[27] : (U = /* @__PURE__ */ jsx(ErrorSnackbar_default, { error: E.error }), h[26] = E.error, h[27] = U);
56
+ let W;
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,
59
+ breadcrumbData: H,
60
+ previewPanelOpen: _,
61
+ onPreviewPanelOpenChange: v,
62
+ isDeveloperMode: y,
63
+ getPreviewUrl: b,
64
+ getEnvironmentPreviewUrl: A,
65
+ environments: k
66
+ }) : !E.isLoading && !E.error ? /* @__PURE__ */ jsx("p", {
53
67
  className: "text-muted-foreground py-8 text-center text-sm",
54
68
  children: "Pipeline not found."
55
- }) : null, m[26] = v.data, m[27] = v.error, m[28] = v.isLoading, m[29] = P) : P = m[29];
56
- let F;
57
- m[30] !== v.isLoading || m[31] !== P ? (F = /* @__PURE__ */ jsx(LoadingCentered_default, {
58
- loading: v.isLoading,
59
- children: P
60
- }), m[30] = v.isLoading, m[31] = P, m[32] = F) : F = m[32];
61
- let I;
62
- return m[33] !== M || m[34] !== N || m[35] !== F ? (I = /* @__PURE__ */ jsxs(MainLayout_default, {
63
- breadcrumbsData: M,
64
- children: [N, F]
65
- }), m[33] = M, m[34] = N, m[35] = F, m[36] = I) : I = m[36], I;
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
+ let G;
71
+ h[39] !== E.isLoading || h[40] !== W ? (G = /* @__PURE__ */ jsx(LoadingCentered_default, {
72
+ loading: E.isLoading,
73
+ children: W
74
+ }), h[39] = E.isLoading, h[40] = W, h[41] = G) : G = h[41];
75
+ let K;
76
+ return h[42] !== U || h[43] !== G ? (K = /* @__PURE__ */ jsx("div", {
77
+ className: "flex h-svh flex-col",
78
+ children: /* @__PURE__ */ jsxs("div", {
79
+ className: "flex-1 overflow-hidden",
80
+ children: [U, G]
81
+ })
82
+ }), h[42] = U, h[43] = G, h[44] = K) : K = h[44], K;
83
+ }
84
+ function _temp(t, f) {
85
+ if (!t.connectionUrl) return "";
86
+ let p = new URLSearchParams({
87
+ url: t.connectionUrl,
88
+ name: t.envName || t.workerId || ""
89
+ });
90
+ return f ? `/embed/env/preview/pipelines/${f}?${p}` : `/embed/env/preview?${p}`;
66
91
  }
67
92
  export { WorkbenchPage as default };
@@ -1,7 +1,7 @@
1
1
  import { useStudio } from "../providers/StudioProvider.js";
2
2
  import { useWorkspace } from "../hooks/useWorkspaces.js";
3
3
  import MainLayout_default from "../components/layout/MainLayout.js";
4
- import ErrorSnackbar_default from "../components/snackbars/ErrorSnackbar.js";
4
+ import ErrorSnackbar_default from "../components/feedback/ErrorSnackbar.js";
5
5
  import ExecutionTimeline_default from "../features/workspaces/components/ExecutionTimeline.js";
6
6
  import { c } from "react/compiler-runtime";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -1,41 +1,39 @@
1
1
  import { __toESM } from "../_virtual/rolldown_runtime.js";
2
+ import { getDocumentsCacheKey, getNamespacesByPipelineCacheKey, getWorkflowCacheKey, getWorkflowsByPipelineCacheKey, getWorkflowsCacheKey } from "../hooks/query-keys.js";
2
3
  import { SseClientEvents } from "../events/sse-client-events.js";
3
4
  import { eventBus } from "../services/eventEmitter.js";
4
5
  import "../services/index.js";
5
6
  import { useStudio } from "./StudioProvider.js";
6
7
  import { require_debounce } from "../node_modules/lodash/debounce.js";
7
- import { getDocumentsCacheKey } from "../hooks/useDocuments.js";
8
- import { getNamespacesByPipelineCacheKey } from "../hooks/useNamespaces.js";
9
- import { getWorkflowCacheKey, getWorkflowsByPipelineCacheKey, getWorkflowsCacheKey } from "../hooks/useWorkflows.js";
10
8
  import { c } from "react/compiler-runtime";
11
9
  import { useEffect, useRef } from "react";
12
- import { useQueryClient } from "@tanstack/react-query";
10
+ import { QueryClient, useQueryClient } from "@tanstack/react-query";
13
11
  var import_debounce = /* @__PURE__ */ __toESM(require_debounce(), 1), DEBOUNCE_MS = 300;
14
- function createDebouncedInvalidator(e, u) {
12
+ function createDebouncedInvalidator(e, l) {
15
13
  return (0, import_debounce.default)(() => {
16
- e.invalidateQueries({ queryKey: u });
14
+ e.invalidateQueries({ queryKey: l });
17
15
  }, DEBOUNCE_MS);
18
16
  }
19
17
  function InvalidationEventsProvider() {
20
- let e = c(5), { environment: f } = useStudio(), _ = useQueryClient(), v;
18
+ let e = c(5), { environment: f } = useStudio(), g = useQueryClient(), v;
21
19
  e[0] === Symbol.for("react.memo_cache_sentinel") ? (v = /* @__PURE__ */ new Map(), e[0] = v) : v = e[0];
22
20
  let y = useRef(v), b, x;
23
- return e[1] !== f.id || e[2] !== _ ? (b = () => {
21
+ return e[1] !== f.id || e[2] !== g ? (b = () => {
24
22
  if (!f.id) return;
25
23
  let e = f.id, d = y.current, p = function(e) {
26
- let u = JSON.stringify(e);
27
- d.has(u) || d.set(u, createDebouncedInvalidator(_, e)), d.get(u)();
28
- }, m = eventBus.on(SseClientEvents.WORKFLOW_CREATED, (u) => {
29
- u.namespaceId && p(getWorkflowsCacheKey(e, u.namespaceId)), u.pipelineId && (p(getNamespacesByPipelineCacheKey(e, u.pipelineId)), p(getWorkflowsByPipelineCacheKey(e, u.pipelineId)));
30
- }), h = eventBus.on(SseClientEvents.WORKFLOW_UPDATED, (u) => {
31
- u.id && p(getWorkflowCacheKey(e, u.id)), u.namespaceId && p(getWorkflowsCacheKey(e, u.namespaceId)), u.pipelineId && (p(getNamespacesByPipelineCacheKey(e, u.pipelineId)), p(getWorkflowsByPipelineCacheKey(e, u.pipelineId)));
32
- }), g = eventBus.on(SseClientEvents.DOCUMENT_CREATED, (u) => {
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) => {
33
31
  u.workflowId && p(getDocumentsCacheKey(e, u.workflowId));
34
32
  });
35
33
  return () => {
36
- m(), h(), g(), d.forEach(_temp), d.clear();
34
+ m(), h(), _(), d.forEach(_temp), d.clear();
37
35
  };
38
- }, x = [_, f.id], e[1] = f.id, e[2] = _, e[3] = b, e[4] = x) : (b = e[3], x = e[4]), useEffect(b, x), null;
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;
39
37
  }
40
38
  function _temp(e) {
41
39
  return e.cancel();
@@ -0,0 +1,21 @@
1
+ import { c } from "react/compiler-runtime";
2
+ import { useState } from "react";
3
+ import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
4
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
5
+ function QueryProvider(o) {
6
+ let s = c(5), { children: l } = o, [u] = useState(_temp), d;
7
+ s[0] === l ? d = s[1] : (d = /* @__PURE__ */ jsx(Fragment$1, { children: l }), s[0] = l, s[1] = d);
8
+ let f;
9
+ return s[2] !== u || s[3] !== d ? (f = /* @__PURE__ */ jsx(QueryClientProvider, {
10
+ client: u,
11
+ children: d
12
+ }), s[2] = u, s[3] = d, s[4] = f) : f = s[4], f;
13
+ }
14
+ function _temp() {
15
+ return new QueryClient({ defaultOptions: { queries: {
16
+ staleTime: 6e4,
17
+ refetchOnWindowFocus: !1,
18
+ retry: 1
19
+ } } });
20
+ }
21
+ export { QueryProvider };
@@ -17,5 +17,5 @@ const StudioProvider = (r) => {
17
17
  let e = useContext(StudioContext);
18
18
  if (!e) throw Error("useStudio must be used within StudioProvider");
19
19
  return e;
20
- };
21
- export { StudioProvider, useStudio };
20
+ }, useStudioOptional = () => useContext(StudioContext);
21
+ export { StudioProvider, useStudio, useStudioOptional };
@@ -3,14 +3,24 @@ import { useNavigate } from "react-router-dom";
3
3
  var LocalRouter = class {
4
4
  navigate;
5
5
  envId;
6
- constructor(e, t) {
7
- this.navigate = e, this.envId = t;
6
+ embedPrefix;
7
+ constructor(e, t, n = "/embed") {
8
+ this.navigate = e, this.envId = t, this.embedPrefix = n;
8
9
  }
9
10
  async navigateToHome() {
10
11
  await this.navigate("/");
11
12
  }
13
+ getEnvironmentInfo() {
14
+ return "/info";
15
+ }
12
16
  async navigateToEnvironmentInfo() {
13
- await this.navigate("/info");
17
+ await this.navigate(this.getEnvironmentInfo());
18
+ }
19
+ getRuns() {
20
+ return "/runs";
21
+ }
22
+ getRunsActionRequired() {
23
+ return "/runs/action-required";
14
24
  }
15
25
  getDashboard() {
16
26
  return "/dashboard";
@@ -58,7 +68,10 @@ var LocalRouter = class {
58
68
  await this.navigate(`/workspaces/${e}/pipelines/${t}/namespaces/${n}`);
59
69
  }
60
70
  getEmbedPipeline(e) {
61
- return `/embed/pipelines/${e}`;
71
+ return `${this.embedPrefix}/pipelines/${e}`;
72
+ }
73
+ getPreviewPipeline(e) {
74
+ return `${this.embedPrefix}/preview/pipelines/${e}`;
62
75
  }
63
76
  getCurrentEnvironmentId() {
64
77
  return this.envId;
@@ -67,8 +80,8 @@ var LocalRouter = class {
67
80
  return "local";
68
81
  }
69
82
  };
70
- const useRouter = (r) => {
71
- let i = c(3), a = useNavigate(), o;
72
- return i[0] !== r || i[1] !== a ? (o = new LocalRouter(a, r), i[0] = r, i[1] = a, i[2] = o) : o = i[2], o;
83
+ const useRouter = (r, i) => {
84
+ let a = c(4), o = useNavigate(), s;
85
+ return a[0] !== i || a[1] !== r || a[2] !== o ? (s = new LocalRouter(o, r, i), a[0] = i, a[1] = r, a[2] = o, a[3] = s) : s = a[3], s;
73
86
  };
74
87
  export { LocalRouter, useRouter };
@@ -1,12 +1,6 @@
1
- import { ApiClientEvents } from "../events/api-client-events.js";
2
- import { eventBus } from "./eventEmitter.js";
3
- import axios from "axios";
4
- import { ApiV1AuthApi, Configuration } from "@loopstack/api-client";
5
- function createApiClient(a) {
6
- let o = new Configuration({ baseOptions: {
7
- withCredentials: !0,
8
- headers: { "Content-Type": "application/json" }
9
- } }), s = axios.create();
10
- return s.interceptors.response.use((e) => e, (i) => ([401, 403].includes(i.response?.status) && eventBus.emit(ApiClientEvents.UNAUTHORIZED, a.id), i.code === "ERR_NETWORK" && eventBus.emit(ApiClientEvents.ERR_NETWORK, a.id), Promise.reject(i))), { auth: new ApiV1AuthApi(o, a.url, s) };
1
+ import { createAxiosClient } from "../api/client.js";
2
+ import { createApi } from "../api/index.js";
3
+ function createApiClient(n) {
4
+ return { auth: createApi(createAxiosClient(n.url, n.id)).auth };
11
5
  }
12
6
  export { createApiClient };
@@ -1,2 +1,2 @@
1
- import { eventBus } from "./eventEmitter.js";
2
1
  import { createApiClient } from "./createApiClient.js";
2
+ import { eventBus } from "./eventEmitter.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loopstack/loopstack-studio",
3
- "version": "0.21.3",
3
+ "version": "0.23.0",
4
4
  "repository": "loopstack-ai/loopstack-studio",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -26,8 +26,7 @@
26
26
  "dependencies": {
27
27
  "@fontsource/roboto": "^5.2.10",
28
28
  "@hookform/resolvers": "^5.2.2",
29
- "@loopstack/api-client": "^0.20.1",
30
- "@loopstack/contracts": "^0.22.0",
29
+ "@loopstack/contracts": "^0.23.0",
31
30
  "@radix-ui/react-accordion": "^1.2.12",
32
31
  "@radix-ui/react-alert-dialog": "^1.1.15",
33
32
  "@radix-ui/react-avatar": "^1.1.11",
@@ -1,40 +0,0 @@
1
- import DocumentItem_default from "./DocumentItem.js";
2
- import { c } from "react/compiler-runtime";
3
- import React, { useEffect } from "react";
4
- import { WorkflowState } from "@loopstack/api-client";
5
- import { jsx } from "react/jsx-runtime";
6
- import { useParams } from "react-router-dom";
7
- var DocumentList_default = (i) => {
8
- let s = c(23), { pipeline: l, workflow: u, documents: d, scrollTo: f, settings: p } = i, { workflowId: m, clickId: h } = useParams(), g;
9
- s[0] !== m || s[1] !== f || s[2] !== u.id ? (g = () => {
10
- m === u.id && f(u.id);
11
- }, s[0] = m, s[1] = f, s[2] = u.id, s[3] = g) : g = s[3];
12
- let _;
13
- s[4] !== h || s[5] !== m || s[6] !== f || s[7] !== u.id ? (_ = [
14
- u.id,
15
- m,
16
- h,
17
- f
18
- ], s[4] = h, s[5] = m, s[6] = f, s[7] = u.id, s[8] = _) : _ = s[8], useEffect(g, _);
19
- let v = u.status === WorkflowState.Waiting, y;
20
- if (s[9] !== d || s[10] !== v || s[11] !== l || s[12] !== p || s[13] !== u) {
21
- let r;
22
- s[15] !== d.length || s[16] !== v || s[17] !== l || s[18] !== p || s[19] !== u ? (r = (r, i) => {
23
- let a = r, o = r.place === u.place || !!a.meta?.enableAtPlaces?.includes(u.place);
24
- return /* @__PURE__ */ jsx(DocumentItem_default, {
25
- document: r,
26
- workflow: u,
27
- pipeline: l,
28
- isActive: v && o,
29
- isLastItem: i === d.length - 1,
30
- settings: p
31
- }, r.id);
32
- }, s[15] = d.length, s[16] = v, s[17] = l, s[18] = p, s[19] = u, s[20] = r) : r = s[20], y = d.map(r), s[9] = d, s[10] = v, s[11] = l, s[12] = p, s[13] = u, s[14] = y;
33
- } else y = s[14];
34
- let b;
35
- return s[21] === y ? b = s[22] : (b = /* @__PURE__ */ jsx("div", {
36
- className: "flex flex-col gap-6",
37
- children: y
38
- }), s[21] = y, s[22] = b), b;
39
- };
40
- export { DocumentList_default as default };