@loopstack/loopstack-studio 0.23.0 → 0.24.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 (90) hide show
  1. package/dist/api/index.js +12 -10
  2. package/dist/api/secrets.js +16 -0
  3. package/dist/components/dynamic-form/ArrayController.js +68 -64
  4. package/dist/components/dynamic-form/Form.js +56 -27
  5. package/dist/components/dynamic-form/FormElement.js +1 -1
  6. package/dist/components/dynamic-form/FormElementHeader.js +2 -2
  7. package/dist/components/dynamic-form/InputController.js +3 -1
  8. package/dist/components/dynamic-form/ObjectController.js +24 -21
  9. package/dist/components/dynamic-form/fields/BaseFieldWrapper.js +1 -1
  10. package/dist/components/dynamic-form/fields/InputField.js +20 -19
  11. package/dist/components/dynamic-form/fields/MarkdownViewField.js +20 -0
  12. package/dist/components/dynamic-form/fields/RadioField.js +18 -18
  13. package/dist/components/dynamic-form/fields/SelectField.js +19 -19
  14. package/dist/components/dynamic-form/fields/TextareaField.js +17 -17
  15. package/dist/components/layout/MainLayout.js +18 -31
  16. package/dist/components/layout/StudioSidebar.js +168 -108
  17. package/dist/components/page/PageBreadcrumbs.js +79 -32
  18. package/dist/components/ui-widgets/UiWidget.js +36 -27
  19. package/dist/components/ui-widgets/widgets/SecretInput.js +42 -0
  20. package/dist/features/code-explorer/components/CodeExplorerTreeNode.js +80 -4
  21. package/dist/features/code-explorer/components/FileContentViewer.js +47 -30
  22. package/dist/features/code-explorer/components/FileTabsBar.js +3 -190
  23. package/dist/features/code-explorer/components/FileTabsBarBase.js +190 -0
  24. package/dist/features/code-explorer/index.js +2 -2
  25. package/dist/features/code-explorer/providers/CodeExplorerProvider.js +2 -162
  26. package/dist/features/code-explorer/utils/fileIcons.js +7 -4
  27. package/dist/features/debug/components/PipelineFlowViewer.js +46 -45
  28. package/dist/features/debug/components/pipeline-flow/WorkflowGraph.js +19 -19
  29. package/dist/features/documents/DocumentRenderer.js +20 -15
  30. package/dist/features/documents/components/DocumentList.js +5 -1
  31. package/dist/features/documents/renderers/AiMessage.js +11 -11
  32. package/dist/features/documents/renderers/ClaudeMessage.js +96 -0
  33. package/dist/features/documents/renderers/DocumentFormRenderer.js +17 -11
  34. package/dist/features/workbench/Workbench.js +64 -80
  35. package/dist/features/workbench/WorkflowItem.js +5 -5
  36. package/dist/features/workbench/components/RemoteFileTabsBar.js +18 -0
  37. package/dist/features/workbench/components/RemoteFileTree.js +90 -0
  38. package/dist/features/workbench/components/WorkbenchFilesPanel.js +67 -0
  39. package/dist/features/workbench/components/WorkbenchFloatingPanel.js +57 -49
  40. package/dist/features/workbench/components/WorkbenchFlowPanel.js +2 -2
  41. package/dist/features/workbench/components/WorkbenchIconSidebar.js +48 -28
  42. package/dist/features/workbench/components/WorkbenchSecretsPanel.js +182 -0
  43. package/dist/features/workbench/hooks/useWorkflowData.js +4 -4
  44. package/dist/features/workbench/providers/RemoteFileExplorerProvider.js +160 -0
  45. package/dist/features/workbench/providers/WorkbenchLayoutProvider.js +46 -43
  46. package/dist/features/workspaces/components/PipelineForm.js +1 -1
  47. package/dist/features/workspaces/components/WorkspaceHomePage.js +93 -0
  48. package/dist/hooks/index.js +1 -1
  49. package/dist/hooks/query-keys.js +41 -34
  50. package/dist/hooks/useFiles.js +1 -43
  51. package/dist/hooks/useSecrets.js +69 -0
  52. package/dist/index.d.ts +49 -0
  53. package/dist/index.js +3 -2
  54. package/dist/node_modules/@xyflow/react/dist/esm/index.js +1 -1
  55. package/dist/pages/DashboardPage.js +87 -35
  56. package/dist/pages/EmbedWorkbenchPage.js +43 -39
  57. package/dist/pages/PipelineDebugPage.js +1 -1
  58. package/dist/pages/PreviewWorkbenchPage.js +167 -70
  59. package/dist/pages/WorkspacePage.js +102 -50
  60. package/dist/pages/WorkspaceRunsPage.js +71 -0
  61. package/dist/routing/LocalRouter.js +6 -0
  62. package/dist/types/ai.types.js +13 -0
  63. package/package.json +2 -3
  64. package/dist/node_modules/@ai-sdk/provider/dist/index.js +0 -65
  65. package/dist/node_modules/@ai-sdk/provider-utils/dist/index.js +0 -1008
  66. package/dist/node_modules/ai/dist/index.js +0 -1083
  67. package/dist/node_modules/zod/v3/ZodError.js +0 -79
  68. package/dist/node_modules/zod/v3/errors.js +0 -6
  69. package/dist/node_modules/zod/v3/helpers/errorUtil.js +0 -5
  70. package/dist/node_modules/zod/v3/helpers/parseUtil.js +0 -90
  71. package/dist/node_modules/zod/v3/helpers/util.js +0 -72
  72. package/dist/node_modules/zod/v3/locales/en.js +0 -58
  73. package/dist/node_modules/zod/v3/types.js +0 -2425
  74. package/dist/node_modules/zod/v4/classic/errors.js +0 -21
  75. package/dist/node_modules/zod/v4/classic/iso.js +0 -29
  76. package/dist/node_modules/zod/v4/classic/parse.js +0 -4
  77. package/dist/node_modules/zod/v4/classic/schemas.js +0 -392
  78. package/dist/node_modules/zod/v4/core/api.js +0 -532
  79. package/dist/node_modules/zod/v4/core/checks.js +0 -283
  80. package/dist/node_modules/zod/v4/core/core.js +0 -44
  81. package/dist/node_modules/zod/v4/core/doc.js +0 -21
  82. package/dist/node_modules/zod/v4/core/errors.js +0 -40
  83. package/dist/node_modules/zod/v4/core/json-schema-processors.js +0 -305
  84. package/dist/node_modules/zod/v4/core/parse.js +0 -66
  85. package/dist/node_modules/zod/v4/core/regexes.js +0 -28
  86. package/dist/node_modules/zod/v4/core/registries.js +0 -38
  87. package/dist/node_modules/zod/v4/core/schemas.js +0 -863
  88. package/dist/node_modules/zod/v4/core/to-json-schema.js +0 -220
  89. package/dist/node_modules/zod/v4/core/util.js +0 -267
  90. package/dist/node_modules/zod/v4/core/versions.js +0 -6
@@ -1,41 +1,88 @@
1
1
  import { cn } from "../../lib/utils.js";
2
- import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "../ui/breadcrumb.js";
2
+ import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from "../ui/breadcrumb.js";
3
3
  import { c } from "react/compiler-runtime";
4
- import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { useNavigate } from "react-router-dom";
6
6
  import { ChevronRight } from "lucide-react";
7
- var PageBreadcrumbs_default = (p) => {
8
- let m = c(15), { breadcrumbData: h, className: g } = p, _ = useNavigate(), v;
9
- m[0] === _ ? v = m[1] : (v = (e, d) => {
10
- e.preventDefault(), _(d);
11
- }, m[0] = _, m[1] = v);
12
- let y = v, b;
13
- m[2] === g ? b = m[3] : (b = cn("ml-3", g), m[2] = g, m[3] = b);
14
- let x;
15
- if (m[4] !== h || m[5] !== y) {
7
+ var PageBreadcrumbs_default = (g) => {
8
+ let _ = c(26), { breadcrumbData: v, className: y } = g, b = useNavigate(), x;
9
+ _[0] === b ? x = _[1] : (x = (e, m) => {
10
+ e.preventDefault(), b(m);
11
+ }, _[0] = b, _[1] = x);
12
+ let S = x, C = _temp, w = v.length > 2, T = v[0], E = v[v.length - 1], D;
13
+ _[2] === y ? D = _[3] : (D = cn("ml-3 min-w-0 max-w-full", y), _[2] = y, _[3] = D);
14
+ let O;
15
+ _[4] !== v.length || _[5] !== T || _[6] !== S || _[7] !== w || _[8] !== E ? (O = v.length <= 1 ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
16
+ /* @__PURE__ */ jsx(BreadcrumbItem, {
17
+ className: "min-w-0",
18
+ children: T.current ? /* @__PURE__ */ jsx(BreadcrumbPage, {
19
+ className: "flex min-w-0 items-center gap-2",
20
+ children: C(T)
21
+ }) : /* @__PURE__ */ jsx(BreadcrumbLink, {
22
+ href: T.href,
23
+ onClick: (e) => T.href && S(e, T.href),
24
+ className: "flex min-w-0 items-center gap-2",
25
+ title: T.label,
26
+ children: C(T)
27
+ })
28
+ }),
29
+ w ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(BreadcrumbSeparator, { children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }) }), /* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(BreadcrumbEllipsis, {}) })] }) : null,
30
+ /* @__PURE__ */ jsx(BreadcrumbSeparator, { children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }) }),
31
+ /* @__PURE__ */ jsx(BreadcrumbItem, {
32
+ className: "min-w-0",
33
+ children: /* @__PURE__ */ jsx(BreadcrumbPage, {
34
+ className: "flex min-w-0 items-center gap-2",
35
+ title: E.label,
36
+ children: C(E)
37
+ })
38
+ })
39
+ ] }), _[4] = v.length, _[5] = T, _[6] = S, _[7] = w, _[8] = E, _[9] = O) : O = _[9];
40
+ let k;
41
+ _[10] === O ? k = _[11] : (k = /* @__PURE__ */ jsx(BreadcrumbList, {
42
+ className: "flex-nowrap overflow-hidden sm:hidden",
43
+ children: O
44
+ }), _[10] = O, _[11] = k);
45
+ let A;
46
+ if (_[12] !== v || _[13] !== S) {
16
47
  let e;
17
- m[7] !== h.length || m[8] !== y ? (e = (e, d) => {
18
- let f = d === h.length - 1;
48
+ _[15] !== v.length || _[16] !== S ? (e = (e, m) => {
49
+ let h = m === v.length - 1;
19
50
  return /* @__PURE__ */ jsxs("div", {
20
51
  className: "contents",
21
- children: [/* @__PURE__ */ jsx(BreadcrumbItem, { children: f || e.current ? /* @__PURE__ */ jsxs(BreadcrumbPage, {
22
- className: "flex items-center gap-2",
23
- children: [e.icon, e.label]
24
- }) : /* @__PURE__ */ jsxs(BreadcrumbLink, {
25
- href: e.href,
26
- onClick: (d) => e.href && y(d, e.href),
27
- className: "flex items-center gap-2",
28
- children: [e.icon, e.label]
29
- }) }), !f && /* @__PURE__ */ jsx(BreadcrumbSeparator, { children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }) })]
30
- }, d);
31
- }, m[7] = h.length, m[8] = y, m[9] = e) : e = m[9], x = h.map(e), m[4] = h, m[5] = y, m[6] = x;
32
- } else x = m[6];
33
- let S;
34
- m[10] === x ? S = m[11] : (S = /* @__PURE__ */ jsx(Breadcrumb, { children: /* @__PURE__ */ jsx(BreadcrumbList, { children: x }) }), m[10] = x, m[11] = S);
35
- let C;
36
- return m[12] !== b || m[13] !== S ? (C = /* @__PURE__ */ jsx("div", {
37
- className: b,
38
- children: S
39
- }), m[12] = b, m[13] = S, m[14] = C) : C = m[14], C;
52
+ children: [/* @__PURE__ */ jsx(BreadcrumbItem, {
53
+ className: "min-w-0",
54
+ children: h || e.current ? /* @__PURE__ */ jsx(BreadcrumbPage, {
55
+ className: "flex min-w-0 items-center gap-2",
56
+ title: e.label,
57
+ children: C(e)
58
+ }) : /* @__PURE__ */ jsx(BreadcrumbLink, {
59
+ href: e.href,
60
+ onClick: (m) => e.href && S(m, e.href),
61
+ className: "flex min-w-0 items-center gap-2",
62
+ title: e.label,
63
+ children: C(e)
64
+ })
65
+ }), !h && /* @__PURE__ */ jsx(BreadcrumbSeparator, { children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4" }) })]
66
+ }, m);
67
+ }, _[15] = v.length, _[16] = S, _[17] = e) : e = _[17], A = v.map(e), _[12] = v, _[13] = S, _[14] = A;
68
+ } else A = _[14];
69
+ let j;
70
+ _[18] === A ? j = _[19] : (j = /* @__PURE__ */ jsx(BreadcrumbList, {
71
+ className: "hidden flex-nowrap overflow-hidden sm:flex",
72
+ children: A
73
+ }), _[18] = A, _[19] = j);
74
+ let M;
75
+ _[20] !== k || _[21] !== j ? (M = /* @__PURE__ */ jsxs(Breadcrumb, { children: [k, j] }), _[20] = k, _[21] = j, _[22] = M) : M = _[22];
76
+ let N;
77
+ return _[23] !== D || _[24] !== M ? (N = /* @__PURE__ */ jsx("div", {
78
+ className: D,
79
+ children: M
80
+ }), _[23] = D, _[24] = M, _[25] = N) : N = _[25], N;
40
81
  };
82
+ function _temp(e) {
83
+ return /* @__PURE__ */ jsxs(Fragment, { children: [e.icon, /* @__PURE__ */ jsx("span", {
84
+ className: "min-w-0 truncate",
85
+ children: e.label
86
+ })] });
87
+ }
41
88
  export { PageBreadcrumbs_default as default };
@@ -1,48 +1,57 @@
1
1
  import AiPromptInput_default from "./widgets/AiPromptInput.js";
2
2
  import { ButtonFullWidth } from "./widgets/ButtonFullWidth.js";
3
3
  import { SandboxRun } from "./widgets/SandboxRun.js";
4
+ import { SecretInput } from "./widgets/SecretInput.js";
4
5
  import { SubmitButton } from "./widgets/SubmitButton.js";
5
6
  import { c } from "react/compiler-runtime";
6
7
  import React from "react";
7
8
  import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
8
- var UiWidget_default = (s) => {
9
- let l = c(18), { config: u, onSubmit: d, disabled: f, isLoading: p } = s, m = u.options;
10
- switch (u.widget) {
9
+ var UiWidget_default = (l) => {
10
+ let u = c(22), { config: d, onSubmit: f, disabled: p, isLoading: m } = l, h = d.options;
11
+ switch (d.widget) {
11
12
  case "prompt-input": {
12
- let a;
13
- return l[0] !== f || l[1] !== d || l[2] !== m ? (a = /* @__PURE__ */ jsx(AiPromptInput_default, {
14
- disabled: f,
15
- onSubmit: d,
16
- ui: m
17
- }), l[0] = f, l[1] = d, l[2] = m, l[3] = a) : a = l[3], a;
13
+ let o;
14
+ return u[0] !== p || u[1] !== f || u[2] !== h ? (o = /* @__PURE__ */ jsx(AiPromptInput_default, {
15
+ disabled: p,
16
+ onSubmit: f,
17
+ ui: h
18
+ }), u[0] = p, u[1] = f, u[2] = h, u[3] = o) : o = u[3], o;
18
19
  }
19
20
  case "button": {
20
- let e = m, a;
21
- return l[4] !== f || l[5] !== p || l[6] !== d || l[7] !== e ? (a = /* @__PURE__ */ jsx(SubmitButton, {
21
+ let e = h, o;
22
+ return u[4] !== p || u[5] !== m || u[6] !== f || u[7] !== e ? (o = /* @__PURE__ */ jsx(SubmitButton, {
22
23
  ui: e,
23
- disabled: f,
24
- onClick: d,
25
- isLoading: p
26
- }), l[4] = f, l[5] = p, l[6] = d, l[7] = e, l[8] = a) : a = l[8], a;
24
+ disabled: p,
25
+ onClick: f,
26
+ isLoading: m
27
+ }), u[4] = p, u[5] = m, u[6] = f, u[7] = e, u[8] = o) : o = u[8], o;
27
28
  }
28
29
  case "button-full-w": {
29
- let e = m, o;
30
- return l[9] !== f || l[10] !== p || l[11] !== d || l[12] !== e ? (o = /* @__PURE__ */ jsx(ButtonFullWidth, {
30
+ let e = h, s;
31
+ return u[9] !== p || u[10] !== m || u[11] !== f || u[12] !== e ? (s = /* @__PURE__ */ jsx(ButtonFullWidth, {
31
32
  ui: e,
32
- disabled: f,
33
- onClick: d,
34
- isLoading: p
35
- }), l[9] = f, l[10] = p, l[11] = d, l[12] = e, l[13] = o) : o = l[13], o;
33
+ disabled: p,
34
+ onClick: f,
35
+ isLoading: m
36
+ }), u[9] = p, u[10] = m, u[11] = f, u[12] = e, u[13] = s) : s = u[13], s;
36
37
  }
37
38
  case "sandbox-run": {
38
- let e = m, a;
39
- return l[14] !== f || l[15] !== e ? (a = /* @__PURE__ */ jsx(SandboxRun, {
39
+ let e = h, o;
40
+ return u[14] !== p || u[15] !== e ? (o = /* @__PURE__ */ jsx(SandboxRun, {
40
41
  ui: e,
41
- disabled: f
42
- }), l[14] = f, l[15] = e, l[16] = a) : a = l[16], a;
42
+ disabled: p
43
+ }), u[14] = p, u[15] = e, u[16] = o) : o = u[16], o;
44
+ }
45
+ case "secret-input": {
46
+ let e = h, o;
47
+ return u[17] !== p || u[18] !== f || u[19] !== e ? (o = /* @__PURE__ */ jsx(SecretInput, {
48
+ ui: e,
49
+ disabled: p,
50
+ onSubmit: f
51
+ }), u[17] = p, u[18] = f, u[19] = e, u[20] = o) : o = u[20], o;
43
52
  }
44
53
  }
45
- let h;
46
- return l[17] === Symbol.for("react.memo_cache_sentinel") ? (h = /* @__PURE__ */ jsx(Fragment$1, {}), l[17] = h) : h = l[17], h;
54
+ let g;
55
+ return u[21] === Symbol.for("react.memo_cache_sentinel") ? (g = /* @__PURE__ */ jsx(Fragment$1, {}), u[21] = g) : g = u[21], g;
47
56
  };
48
57
  export { UiWidget_default as default };
@@ -0,0 +1,42 @@
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 };
@@ -1,6 +1,82 @@
1
- import "../../../lib/utils.js";
2
- import "../../../components/ui/button.js";
3
- import "../../../components/ui/collapsible.js";
4
- import "../utils/fileIcons.js";
1
+ import { cn } from "../../../lib/utils.js";
2
+ import { Button } from "../../../components/ui/button.js";
3
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../../../components/ui/collapsible.js";
4
+ import { getFileIcon, getFolderIcon } from "../utils/fileIcons.js";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
6
  import { ChevronDown, ChevronRight, X } from "lucide-react";
7
+ var INDENT_PX = 16, BASE_PADDING_PX = 8;
8
+ function CodeExplorerTreeNode({ node: h, depth: g, onSelectFile: _, onClearSelection: v, onCloseFile: y, isSelected: b = !1, selectedFileId: x, expandedFolders: S = /* @__PURE__ */ new Set(), toggleFolder: C }) {
9
+ let w = S.has(h.id), T = g * INDENT_PX + BASE_PADDING_PX, E = x === h.id || b;
10
+ if (h.type === "file") {
11
+ let m = getFileIcon(h.name);
12
+ return /* @__PURE__ */ jsxs("div", {
13
+ className: cn("flex w-full min-w-0 items-center gap-2 rounded-sm py-1 group", "text-muted-foreground", E && "bg-muted"),
14
+ style: { paddingLeft: T },
15
+ children: [/* @__PURE__ */ jsxs("button", {
16
+ type: "button",
17
+ className: cn("flex flex-1 min-w-0 items-center gap-2 rounded-sm text-left text-sm hover:bg-muted/50", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"),
18
+ onClick: () => _?.(h),
19
+ "aria-label": `Select file ${h.name}`,
20
+ children: [/* @__PURE__ */ jsx(m, {
21
+ className: "h-4 w-4 shrink-0 text-muted-foreground",
22
+ "aria-hidden": !0
23
+ }), /* @__PURE__ */ jsx("span", {
24
+ className: "truncate",
25
+ children: h.name
26
+ })]
27
+ }), E && (y || v) && /* @__PURE__ */ jsx(Button, {
28
+ variant: "ghost",
29
+ size: "icon",
30
+ className: "h-6 w-6 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity",
31
+ onClick: (e) => {
32
+ e.stopPropagation(), y ? y(h) : v && v();
33
+ },
34
+ "aria-label": "Close file",
35
+ children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
36
+ })]
37
+ });
38
+ }
39
+ let D = h.children && h.children.length > 0, O = getFolderIcon(w);
40
+ return /* @__PURE__ */ jsxs(Collapsible, {
41
+ open: w,
42
+ onOpenChange: () => {
43
+ C && C(h.id);
44
+ },
45
+ children: [/* @__PURE__ */ jsxs(CollapsibleTrigger, {
46
+ className: cn("flex w-full min-w-0 items-center gap-1 rounded-sm py-1 text-left text-sm hover:bg-muted", "text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", "disabled:cursor-default disabled:opacity-50"),
47
+ style: { paddingLeft: T },
48
+ disabled: !D,
49
+ "aria-label": `${w ? "Collapse" : "Expand"} folder ${h.name}`,
50
+ children: [
51
+ D ? jsx(w ? ChevronDown : ChevronRight, {
52
+ className: "h-4 w-4 shrink-0",
53
+ "aria-hidden": !0
54
+ }) : /* @__PURE__ */ jsx("span", {
55
+ className: "w-4 shrink-0",
56
+ "aria-hidden": !0
57
+ }),
58
+ /* @__PURE__ */ jsx(O, {
59
+ className: "h-4 w-4 shrink-0 text-muted-foreground",
60
+ "aria-hidden": !0
61
+ }),
62
+ /* @__PURE__ */ jsx("span", {
63
+ className: "truncate",
64
+ children: h.name
65
+ })
66
+ ]
67
+ }), D && /* @__PURE__ */ jsx(CollapsibleContent, {
68
+ className: "h-full",
69
+ children: h.children.map((e) => /* @__PURE__ */ jsx(CodeExplorerTreeNode, {
70
+ node: e,
71
+ depth: g + 1,
72
+ onSelectFile: _,
73
+ onClearSelection: v,
74
+ onCloseFile: y,
75
+ selectedFileId: x,
76
+ expandedFolders: S,
77
+ toggleFolder: C
78
+ }, e.id))
79
+ })]
80
+ });
81
+ }
82
+ export { CodeExplorerTreeNode };
@@ -68,7 +68,7 @@ function getLanguageForFileName(e) {
68
68
  return EXTENSION_LANGUAGE[e.includes(".") ? e.slice(e.lastIndexOf(".")).toLowerCase() : ""] ?? "plaintext";
69
69
  }
70
70
  function FileContentViewer(v) {
71
- let y = c(34), { selectedFile: b, content: x, workflowConfig: S, isLoading: C, className: w } = v, T = S === void 0 ? null : S, E = C === void 0 ? !1 : C;
71
+ let y = c(39), { selectedFile: b, content: x, workflowConfig: S, isLoading: C, className: w } = v, T = S === void 0 ? null : S, E = C === void 0 ? !1 : C;
72
72
  if (!b) {
73
73
  let h;
74
74
  y[0] === w ? h = y[1] : (h = cn("flex flex-1 items-center justify-center bg-background", w), y[0] = w, y[1] = h);
@@ -83,8 +83,8 @@ function FileContentViewer(v) {
83
83
  children: g
84
84
  }), y[3] = h, y[4] = _), _;
85
85
  }
86
- let D = isBinaryFileName(b.name), O = x ?? (D ? null : `// ${b.path ?? b.name}\n\n(No content available)`);
87
- if (D && x == null) {
86
+ let D = isBinaryFileName(b.name), O = x != null, k = x ?? "";
87
+ if (D && !O) {
88
88
  let h;
89
89
  y[5] === w ? h = y[6] : (h = cn("flex flex-1 flex-col rounded-lg border bg-background", w), y[5] = w, y[6] = h);
90
90
  let g;
@@ -101,13 +101,16 @@ function FileContentViewer(v) {
101
101
  children: g
102
102
  }), y[8] = h, y[9] = _), _;
103
103
  }
104
- if (E) {
104
+ if (!O && !E) {
105
105
  let h;
106
106
  y[10] === w ? h = y[11] : (h = cn("flex flex-1 flex-col rounded-lg border bg-background", w), y[10] = w, y[11] = h);
107
107
  let g;
108
108
  y[12] === Symbol.for("react.memo_cache_sentinel") ? (g = /* @__PURE__ */ jsx("div", {
109
- className: "flex justify-center p-8",
110
- children: /* @__PURE__ */ jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" })
109
+ className: "flex flex-1 items-center justify-center p-8",
110
+ children: /* @__PURE__ */ jsx("p", {
111
+ className: "text-sm text-destructive",
112
+ children: "Error loading file content"
113
+ })
111
114
  }), y[12] = g) : g = y[12];
112
115
  let _;
113
116
  return y[13] === h ? _ = y[14] : (_ = /* @__PURE__ */ jsx("div", {
@@ -115,16 +118,30 @@ function FileContentViewer(v) {
115
118
  children: g
116
119
  }), y[13] = h, y[14] = _), _;
117
120
  }
118
- let k;
119
- y[15] === b.name ? k = y[16] : (k = getLanguageForFileName(b.name), y[15] = b.name, y[16] = k);
120
- let A = k, j;
121
- y[17] !== A || y[18] !== b.name ? (j = A === "markdown" || b.name.endsWith(".md") || b.name.endsWith(".mdx"), y[17] = A, y[18] = b.name, y[19] = j) : j = y[19];
122
- let M = j, N;
123
- y[20] !== A || y[21] !== b.name ? (N = A === "yaml" || b.name.endsWith(".yaml") || b.name.endsWith(".yml"), y[20] = A, y[21] = b.name, y[22] = N) : N = y[22];
124
- let P = N && T !== null, F;
125
- y[23] === w ? F = y[24] : (F = cn("flex h-full flex-col overflow-hidden rounded-lg border bg-background", w), y[23] = w, y[24] = F);
126
- let I;
127
- y[25] !== O || y[26] !== M || y[27] !== P || y[28] !== A || y[29] !== T ? (I = M && O ? /* @__PURE__ */ jsxs(Tabs, {
121
+ if (E) {
122
+ let h;
123
+ y[15] === w ? h = y[16] : (h = cn("flex flex-1 flex-col rounded-lg border bg-background", w), y[15] = w, y[16] = h);
124
+ let g;
125
+ y[17] === Symbol.for("react.memo_cache_sentinel") ? (g = /* @__PURE__ */ jsx("div", {
126
+ className: "flex justify-center p-8",
127
+ children: /* @__PURE__ */ jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" })
128
+ }), y[17] = g) : g = y[17];
129
+ let _;
130
+ return y[18] === h ? _ = y[19] : (_ = /* @__PURE__ */ jsx("div", {
131
+ className: h,
132
+ children: g
133
+ }), y[18] = h, y[19] = _), _;
134
+ }
135
+ let A;
136
+ y[20] === b.name ? A = y[21] : (A = getLanguageForFileName(b.name), y[20] = b.name, y[21] = A);
137
+ let j = A, M;
138
+ y[22] !== j || y[23] !== b.name ? (M = j === "markdown" || b.name.endsWith(".md") || b.name.endsWith(".mdx"), y[22] = j, y[23] = b.name, y[24] = M) : M = y[24];
139
+ let N = M, P;
140
+ y[25] !== j || y[26] !== b.name ? (P = j === "yaml" || b.name.endsWith(".yaml") || b.name.endsWith(".yml"), y[25] = j, y[26] = b.name, y[27] = P) : P = y[27];
141
+ let F = P && T !== null, I;
142
+ y[28] === w ? I = y[29] : (I = cn("flex h-full flex-col overflow-hidden rounded-lg border bg-background", w), y[28] = w, y[29] = I);
143
+ let L;
144
+ y[30] !== k || y[31] !== N || y[32] !== F || y[33] !== j || y[34] !== T ? (L = N && k ? /* @__PURE__ */ jsxs(Tabs, {
128
145
  defaultValue: "rendered",
129
146
  className: "flex h-full flex-col overflow-hidden",
130
147
  children: [
@@ -145,7 +162,7 @@ function FileContentViewer(v) {
145
162
  className: "h-full",
146
163
  children: /* @__PURE__ */ jsx("div", {
147
164
  className: "p-4",
148
- children: /* @__PURE__ */ jsx(MarkdownContent_default, { content: O })
165
+ children: /* @__PURE__ */ jsx(MarkdownContent_default, { content: k })
149
166
  })
150
167
  })
151
168
  }),
@@ -155,7 +172,7 @@ function FileContentViewer(v) {
155
172
  children: /* @__PURE__ */ jsx(ScrollArea, {
156
173
  className: "flex-1 min-h-0",
157
174
  children: /* @__PURE__ */ jsx(Prism, {
158
- language: A,
175
+ language: j,
159
176
  style: vscDarkPlus,
160
177
  customStyle: {
161
178
  margin: 0,
@@ -165,12 +182,12 @@ function FileContentViewer(v) {
165
182
  showLineNumbers: !0,
166
183
  PreTag: "div",
167
184
  codeTagProps: { style: { fontFamily: "inherit" } },
168
- children: O ?? ""
185
+ children: k ?? ""
169
186
  })
170
187
  })
171
188
  })
172
189
  ]
173
- }) : P && T ? /* @__PURE__ */ jsxs(Tabs, {
190
+ }) : F && T ? /* @__PURE__ */ jsxs(Tabs, {
174
191
  defaultValue: "code",
175
192
  className: "flex h-full flex-col overflow-hidden",
176
193
  children: [
@@ -190,7 +207,7 @@ function FileContentViewer(v) {
190
207
  children: /* @__PURE__ */ jsx(ScrollArea, {
191
208
  className: "flex-1 min-h-0",
192
209
  children: /* @__PURE__ */ jsx(Prism, {
193
- language: A,
210
+ language: j,
194
211
  style: vscDarkPlus,
195
212
  customStyle: {
196
213
  margin: 0,
@@ -200,7 +217,7 @@ function FileContentViewer(v) {
200
217
  showLineNumbers: !0,
201
218
  PreTag: "div",
202
219
  codeTagProps: { style: { fontFamily: "inherit" } },
203
- children: O ?? ""
220
+ children: k ?? ""
204
221
  })
205
222
  })
206
223
  }),
@@ -216,7 +233,7 @@ function FileContentViewer(v) {
216
233
  }) : /* @__PURE__ */ jsx(ScrollArea, {
217
234
  className: "flex-1 min-h-0",
218
235
  children: /* @__PURE__ */ jsx(Prism, {
219
- language: A,
236
+ language: j,
220
237
  style: vscDarkPlus,
221
238
  customStyle: {
222
239
  margin: 0,
@@ -226,13 +243,13 @@ function FileContentViewer(v) {
226
243
  showLineNumbers: !0,
227
244
  PreTag: "div",
228
245
  codeTagProps: { style: { fontFamily: "inherit" } },
229
- children: O ?? ""
246
+ children: k ?? ""
230
247
  })
231
- }), y[25] = O, y[26] = M, y[27] = P, y[28] = A, y[29] = T, y[30] = I) : I = y[30];
232
- let L;
233
- return y[31] !== F || y[32] !== I ? (L = /* @__PURE__ */ jsx("div", {
234
- className: F,
235
- children: I
236
- }), y[31] = F, y[32] = I, y[33] = L) : L = y[33], L;
248
+ }), y[30] = k, y[31] = N, y[32] = F, y[33] = j, y[34] = T, y[35] = L) : L = y[35];
249
+ let R;
250
+ return y[36] !== I || y[37] !== L ? (R = /* @__PURE__ */ jsx("div", {
251
+ className: I,
252
+ children: L
253
+ }), y[36] = I, y[37] = L, y[38] = R) : R = y[38], R;
237
254
  }
238
255
  export { FileContentViewer };