@loopstack/loopstack-studio 0.36.0 → 0.37.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.
@@ -2,7 +2,8 @@ import CompletionMessagePaper_default from "../../../components/messages/Complet
2
2
  import MarkdownContent_default from "../../../components/dynamic-form/MarkdownContent.js";
3
3
  import { c } from "react/compiler-runtime";
4
4
  import React from "react";
5
- import { jsx } from "react/jsx-runtime";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { Info } from "lucide-react";
6
7
  var KNOWN_ROLES = [
7
8
  "system",
8
9
  "user",
@@ -10,13 +11,26 @@ var KNOWN_ROLES = [
10
11
  "tool",
11
12
  "error",
12
13
  "document"
13
- ], DocumentMessageRenderer_default = (a) => {
14
- let o = c(5), { document: s } = a, { role: l, text: u } = s.content, d = KNOWN_ROLES.includes(l ?? "") ? l : void 0, f = u ?? "", p;
15
- o[0] === f ? p = o[1] : (p = /* @__PURE__ */ jsx(MarkdownContent_default, { content: f }), o[0] = f, o[1] = p);
16
- let m;
17
- return o[2] !== d || o[3] !== p ? (m = /* @__PURE__ */ jsx(CompletionMessagePaper_default, {
18
- role: d,
19
- children: p
20
- }), o[2] = d, o[3] = p, o[4] = m) : m = o[4], m;
14
+ ], DocumentMessageRenderer_default = (s) => {
15
+ let l = c(8), { document: u } = s, { role: d, text: f } = u.content, p = KNOWN_ROLES.includes(d ?? "") ? d : void 0;
16
+ if (p === "system") {
17
+ let e;
18
+ l[0] === Symbol.for("react.memo_cache_sentinel") ? (e = /* @__PURE__ */ jsx(Info, { className: "mt-0.5 size-3.5 shrink-0 opacity-70" }), l[0] = e) : e = l[0];
19
+ let o = f ?? "", s;
20
+ return l[1] === o ? s = l[2] : (s = /* @__PURE__ */ jsxs("div", {
21
+ className: "text-muted-foreground flex items-start gap-1.5 px-1 py-0.5 text-sm leading-relaxed [&_p]:m-0",
22
+ children: [e, /* @__PURE__ */ jsx("div", {
23
+ className: "min-w-0",
24
+ children: /* @__PURE__ */ jsx(MarkdownContent_default, { content: o })
25
+ })]
26
+ }), l[1] = o, l[2] = s), s;
27
+ }
28
+ let m = f ?? "", h;
29
+ l[3] === m ? h = l[4] : (h = /* @__PURE__ */ jsx(MarkdownContent_default, { content: m }), l[3] = m, l[4] = h);
30
+ let g;
31
+ return l[5] !== p || l[6] !== h ? (g = /* @__PURE__ */ jsx(CompletionMessagePaper_default, {
32
+ role: p,
33
+ children: h
34
+ }), l[5] = p, l[6] = h, l[7] = g) : g = l[7], g;
21
35
  };
22
36
  export { DocumentMessageRenderer_default as default };
@@ -8,16 +8,50 @@ import { Fragment } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  import { CopyIcon } from "lucide-react";
10
10
  var CopyActions = (e) => {
11
- let _ = c(5), { text: v } = e, y;
12
- _[0] === v ? y = _[1] : (y = () => void navigator.clipboard.writeText(v), _[0] = v, _[1] = y);
11
+ let g = c(5), { text: _ } = e, v;
12
+ g[0] === _ ? v = g[1] : (v = () => void navigator.clipboard.writeText(_), g[0] = _, g[1] = v);
13
+ let y;
14
+ g[2] === Symbol.for("react.memo_cache_sentinel") ? (y = /* @__PURE__ */ jsx(CopyIcon, { className: "size-3" }), g[2] = y) : y = g[2];
13
15
  let b;
14
- _[2] === Symbol.for("react.memo_cache_sentinel") ? (b = /* @__PURE__ */ jsx(CopyIcon, { className: "size-3" }), _[2] = b) : b = _[2];
15
- let x;
16
- return _[3] === y ? x = _[4] : (x = /* @__PURE__ */ jsx(FadeInBlock, { children: /* @__PURE__ */ jsx(MessageActions, { children: /* @__PURE__ */ jsx(MessageAction, {
17
- onClick: y,
16
+ return g[3] === v ? b = g[4] : (b = /* @__PURE__ */ jsx(FadeInBlock, { children: /* @__PURE__ */ jsx(MessageActions, { children: /* @__PURE__ */ jsx(MessageAction, {
17
+ onClick: v,
18
18
  label: "Copy",
19
- children: b
20
- }) }) }), _[3] = y, _[4] = x), x;
19
+ children: y
20
+ }) }) }), g[3] = v, g[4] = b), b;
21
+ };
22
+ function formatTokens(e) {
23
+ return e == null ? null : e >= 1e3 ? `${(e / 1e3).toFixed(1)}k` : String(e);
24
+ }
25
+ var CompletionMeta = (e) => {
26
+ let m = c(21), { meta: h } = e, g;
27
+ if (m[0] !== h.costUsd || m[1] !== h.durationMs || m[2] !== h.model || m[3] !== h.numTurns || m[4] !== h.usage?.cacheCreationInputTokens || m[5] !== h.usage?.cacheReadInputTokens || m[6] !== h.usage?.inputTokens || m[7] !== h.usage?.outputTokens) {
28
+ if (g = [], h.numTurns != null && g.push(`${h.numTurns} turn${h.numTurns === 1 ? "" : "s"}`), h.costUsd != null) {
29
+ let e;
30
+ m[9] === h.costUsd ? e = m[10] : (e = h.costUsd.toFixed(4), m[9] = h.costUsd, m[10] = e), g.push(`$${e}`);
31
+ }
32
+ let e = h.usage?.inputTokens, _;
33
+ m[11] === e ? _ = m[12] : (_ = formatTokens(e), m[11] = e, m[12] = _);
34
+ let v = _, y = h.usage?.outputTokens, b;
35
+ m[13] === y ? b = m[14] : (b = formatTokens(y), m[13] = y, m[14] = b);
36
+ let x = b;
37
+ v && x && g.push(`${v} in / ${x} out`);
38
+ let S = (h.usage?.cacheReadInputTokens ?? 0) + (h.usage?.cacheCreationInputTokens ?? 0);
39
+ if (S) {
40
+ let e;
41
+ m[15] === S ? e = m[16] : (e = formatTokens(S), m[15] = S, m[16] = e), g.push(`${e} cache`);
42
+ }
43
+ if (h.durationMs != null) {
44
+ let e = h.durationMs / 1e3, _;
45
+ m[17] === e ? _ = m[18] : (_ = e.toFixed(1), m[17] = e, m[18] = _), g.push(`${_}s`);
46
+ }
47
+ h.model && g.push(h.model), m[0] = h.costUsd, m[1] = h.durationMs, m[2] = h.model, m[3] = h.numTurns, m[4] = h.usage?.cacheCreationInputTokens, m[5] = h.usage?.cacheReadInputTokens, m[6] = h.usage?.inputTokens, m[7] = h.usage?.outputTokens, m[8] = g;
48
+ } else g = m[8];
49
+ if (!g.length) return null;
50
+ let _ = g.join(" · "), v;
51
+ return m[19] === _ ? v = m[20] : (v = /* @__PURE__ */ jsx("div", {
52
+ className: "text-muted-foreground mt-1 px-1 font-mono text-xs",
53
+ children: _
54
+ }), m[19] = _, m[20] = v), v;
21
55
  };
22
56
  function hasStructuredBlocks(e) {
23
57
  return !!e?.some((e) => e.type !== "text");
@@ -25,81 +59,87 @@ function hasStructuredBlocks(e) {
25
59
  function textFromBlocks(e) {
26
60
  return (e ?? []).filter((e) => e.type === "text").map((e) => e.text).join("\n");
27
61
  }
28
- var LlmMessage_default = (h) => {
29
- let g = c(23), { document: C } = h, w = C.content, T = w.id ?? C.id, E = !!C.meta?.streaming;
30
- if (!hasStructuredBlocks(w.blocks)) {
31
- let h;
32
- g[0] !== w.blocks || g[1] !== w.text ? (h = w.text ?? textFromBlocks(w.blocks), g[0] = w.blocks, g[1] = w.text, g[2] = h) : h = g[2];
33
- let y = h, b;
34
- g[3] !== E || g[4] !== y ? (b = /* @__PURE__ */ jsx(MessageContent, { children: E ? /* @__PURE__ */ jsx(StreamingText, { text: y }) : /* @__PURE__ */ jsx(MessageResponse, { children: y }) }), g[3] = E, g[4] = y, g[5] = b) : b = g[5];
62
+ var LlmMessage_default = (m) => {
63
+ let h = c(31), { document: w } = m, T = w.content, E = T.id ?? w.id, D = !!w.meta?.streaming;
64
+ if (!hasStructuredBlocks(T.blocks)) {
65
+ let m;
66
+ h[0] !== T.blocks || h[1] !== T.text ? (m = T.text ?? textFromBlocks(T.blocks), h[0] = T.blocks, h[1] = T.text, h[2] = m) : m = h[2];
67
+ let v = m, y;
68
+ h[3] !== D || h[4] !== v ? (y = /* @__PURE__ */ jsx(MessageContent, { children: D ? /* @__PURE__ */ jsx(StreamingText, { text: v }) : /* @__PURE__ */ jsx(MessageResponse, { children: v }) }), h[3] = D, h[4] = v, h[5] = y) : y = h[5];
69
+ let b;
70
+ h[6] !== D || h[7] !== T.role || h[8] !== v ? (b = T.role === "assistant" && !D && /* @__PURE__ */ jsx(CopyActions, { text: v }), h[6] = D, h[7] = T.role, h[8] = v, h[9] = b) : b = h[9];
35
71
  let x;
36
- g[6] !== E || g[7] !== w.role || g[8] !== y ? (x = w.role === "assistant" && !E && /* @__PURE__ */ jsx(CopyActions, { text: y }), g[6] = E, g[7] = w.role, g[8] = y, g[9] = x) : x = g[9];
72
+ h[10] !== T.role || h[11] !== y || h[12] !== b ? (x = /* @__PURE__ */ jsxs(Message, {
73
+ from: T.role,
74
+ children: [y, b]
75
+ }), h[10] = T.role, h[11] = y, h[12] = b, h[13] = x) : x = h[13];
37
76
  let S;
38
- return g[10] !== w.role || g[11] !== b || g[12] !== x ? (S = /* @__PURE__ */ jsxs(Message, {
39
- from: w.role,
40
- children: [b, x]
41
- }), g[10] = w.role, g[11] = b, g[12] = x, g[13] = S) : S = g[13], S;
77
+ h[14] === T.meta ? S = h[15] : (S = T.meta && /* @__PURE__ */ jsx(CompletionMeta, { meta: T.meta }), h[14] = T.meta, h[15] = S);
78
+ let C;
79
+ return h[16] !== x || h[17] !== S ? (C = /* @__PURE__ */ jsxs(Fragment, { children: [x, S] }), h[16] = x, h[17] = S, h[18] = C) : C = h[18], C;
42
80
  }
43
- let D;
44
- g[14] === w.blocks ? D = g[15] : (D = w.blocks ?? [], g[14] = w.blocks, g[15] = D);
45
- let O = D, k;
46
- g[16] !== O || g[17] !== E || g[18] !== w.role || g[19] !== T ? (k = O.map((h, g) => {
47
- switch (h.type) {
81
+ let O;
82
+ h[19] === T.blocks ? O = h[20] : (O = T.blocks ?? [], h[19] = T.blocks, h[20] = O);
83
+ let k = O, A;
84
+ h[21] !== k || h[22] !== D || h[23] !== T.role || h[24] !== E ? (A = k.map((m, h) => {
85
+ switch (m.type) {
48
86
  case "text": return /* @__PURE__ */ jsxs(Message, {
49
- from: w.role,
50
- children: [/* @__PURE__ */ jsx(MessageContent, { children: E ? /* @__PURE__ */ jsx(StreamingText, { text: h.text }) : /* @__PURE__ */ jsx(MessageResponse, { children: h.text }) }), w.role === "assistant" && !E && /* @__PURE__ */ jsx(CopyActions, { text: h.text })]
51
- }, `${T}-${g}`);
87
+ from: T.role,
88
+ children: [/* @__PURE__ */ jsx(MessageContent, { children: D ? /* @__PURE__ */ jsx(StreamingText, { text: m.text }) : /* @__PURE__ */ jsx(MessageResponse, { children: m.text }) }), T.role === "assistant" && !D && /* @__PURE__ */ jsx(CopyActions, { text: m.text })]
89
+ }, `${E}-${h}`);
52
90
  case "thinking": return /* @__PURE__ */ jsxs(Reasoning, {
53
91
  className: "w-full",
54
- isStreaming: E,
55
- children: [/* @__PURE__ */ jsx(ReasoningTrigger, {}), /* @__PURE__ */ jsx(ReasoningContent, { children: h.text })]
56
- }, `${T}-${g}`);
92
+ isStreaming: D,
93
+ children: [/* @__PURE__ */ jsx(ReasoningTrigger, {}), /* @__PURE__ */ jsx(ReasoningContent, { children: m.text })]
94
+ }, `${E}-${h}`);
57
95
  case "tool_call": return /* @__PURE__ */ jsx(FadeInBlock, { children: /* @__PURE__ */ jsx(Message, {
58
96
  from: "assistant",
59
97
  children: /* @__PURE__ */ jsxs(Tool, { children: [/* @__PURE__ */ jsx(ToolHeader, {
60
98
  state: "input-available",
61
- title: h.name,
99
+ title: m.name,
62
100
  type: "tool-call"
63
- }), /* @__PURE__ */ jsx(ToolContent, { children: /* @__PURE__ */ jsx(ToolInput, { input: h.args }) })] })
64
- }) }, `${T}-${g}`);
101
+ }), /* @__PURE__ */ jsx(ToolContent, { children: /* @__PURE__ */ jsx(ToolInput, { input: m.args }) })] })
102
+ }) }, `${E}-${h}`);
65
103
  case "tool_result": {
66
- let _;
104
+ let g;
67
105
  try {
68
- _ = JSON.parse(h.content);
106
+ g = JSON.parse(m.content);
69
107
  } catch {
70
- _ = h.content;
108
+ g = m.content;
71
109
  }
72
110
  return /* @__PURE__ */ jsx(FadeInBlock, { children: /* @__PURE__ */ jsx(Message, {
73
111
  from: "assistant",
74
112
  children: /* @__PURE__ */ jsxs(Tool, { children: [/* @__PURE__ */ jsx(ToolHeader, {
75
- state: h.isError ? "output-error" : "output-available",
113
+ state: m.isError ? "output-error" : "output-available",
76
114
  title: "Tool Result",
77
115
  type: "tool-call"
78
116
  }), /* @__PURE__ */ jsx(ToolContent, { children: /* @__PURE__ */ jsx(ToolOutput, {
79
- output: _,
80
- errorText: h.isError ? h.content : ""
117
+ output: g,
118
+ errorText: m.isError ? m.content : ""
81
119
  }) })] })
82
- }) }, `${T}-${g}`);
120
+ }) }, `${E}-${h}`);
83
121
  }
84
122
  case "server_tool_use": {
85
- let _ = O.find((e) => e.type === "server_tool_result" && e.toolUseId === h.id);
123
+ let g = k.find((e) => e.type === "server_tool_result" && e.toolUseId === m.id);
86
124
  return /* @__PURE__ */ jsx(FadeInBlock, { children: /* @__PURE__ */ jsx(Message, {
87
125
  from: "assistant",
88
126
  children: /* @__PURE__ */ jsxs(Tool, { children: [/* @__PURE__ */ jsx(ToolHeader, {
89
- state: _ ? "output-available" : "input-available",
90
- title: h.name,
127
+ state: g ? "output-available" : "input-available",
128
+ title: m.name,
91
129
  type: "tool-call"
92
- }), /* @__PURE__ */ jsxs(ToolContent, { children: [/* @__PURE__ */ jsx(ToolInput, { input: h.input }), _ && /* @__PURE__ */ jsx(ToolOutput, {
93
- output: _.content,
130
+ }), /* @__PURE__ */ jsxs(ToolContent, { children: [/* @__PURE__ */ jsx(ToolInput, { input: m.input }), g && /* @__PURE__ */ jsx(ToolOutput, {
131
+ output: g.content,
94
132
  errorText: ""
95
133
  })] })] })
96
- }) }, `${T}-${g}`);
134
+ }) }, `${E}-${h}`);
97
135
  }
98
136
  case "server_tool_result": return null;
99
137
  default: return null;
100
138
  }
101
- }), g[16] = O, g[17] = E, g[18] = w.role, g[19] = T, g[20] = k) : k = g[20];
102
- let A;
103
- return g[21] === k ? A = g[22] : (A = /* @__PURE__ */ jsx(Fragment, { children: k }), g[21] = k, g[22] = A), A;
139
+ }), h[21] = k, h[22] = D, h[23] = T.role, h[24] = E, h[25] = A) : A = h[25];
140
+ let j;
141
+ h[26] === T.meta ? j = h[27] : (j = T.meta && /* @__PURE__ */ jsx(CompletionMeta, { meta: T.meta }), h[26] = T.meta, h[27] = j);
142
+ let M;
143
+ return h[28] !== A || h[29] !== j ? (M = /* @__PURE__ */ jsxs(Fragment, { children: [A, j] }), h[28] = A, h[29] = j, h[30] = M) : M = h[30], M;
104
144
  };
105
145
  export { LlmMessage_default as default };
@@ -5,6 +5,7 @@ import "../../feature-registry/index.js";
5
5
  import { useWorkbenchLayout } from "../../workbench/providers/WorkbenchLayoutProvider.js";
6
6
  import { SidebarPanel } from "../../workbench/components/SidebarPanel.js";
7
7
  import "../../workbench/index.js";
8
+ import { EnvironmentSelector } from "../../workbench/components/EnvironmentSelector.js";
8
9
  import { FileExplorerProvider, useOptionalFileExplorer } from "../providers/FileExplorerProvider.js";
9
10
  import { FileTabsBar } from "./FileTabsBar.js";
10
11
  import { FileTree } from "./FileTree.js";
@@ -12,109 +13,101 @@ import { c } from "react/compiler-runtime";
12
13
  import { jsx, jsxs } from "react/jsx-runtime";
13
14
  import { Files } from "lucide-react";
14
15
  function FileExplorerContent() {
15
- let i = c(7), a = useOptionalFileExplorer();
16
- if (!a) {
16
+ let o = c(7), s = useOptionalFileExplorer();
17
+ if (!s) {
17
18
  let e;
18
- return i[0] === Symbol.for("react.memo_cache_sentinel") ? (e = /* @__PURE__ */ jsx("div", {
19
+ return o[0] === Symbol.for("react.memo_cache_sentinel") ? (e = /* @__PURE__ */ jsx("div", {
19
20
  className: "flex flex-1 items-center justify-center p-4",
20
21
  children: /* @__PURE__ */ jsx("p", {
21
22
  className: "text-muted-foreground text-sm",
22
23
  children: "File explorer is not available for this workspace."
23
24
  })
24
- }), i[0] = e) : e = i[0], e;
25
+ }), o[0] = e) : e = o[0], e;
25
26
  }
26
- let o;
27
- i[1] === Symbol.for("react.memo_cache_sentinel") ? (o = /* @__PURE__ */ jsx("div", {
27
+ let l;
28
+ o[1] === Symbol.for("react.memo_cache_sentinel") ? (l = /* @__PURE__ */ jsx("div", {
28
29
  className: "w-52 shrink-0 overflow-auto border-r bg-muted/40",
29
30
  children: /* @__PURE__ */ jsx(FileTree, {})
30
- }), i[1] = o) : o = i[1];
31
- let s;
32
- i[2] === Symbol.for("react.memo_cache_sentinel") ? (s = /* @__PURE__ */ jsx(FileTabsBar, {}), i[2] = s) : s = i[2];
33
- let p;
34
- return i[3] !== a.fileContent || i[4] !== a.isContentLoading || i[5] !== a.selectedFile ? (p = /* @__PURE__ */ jsxs("div", {
31
+ }), o[1] = l) : l = o[1];
32
+ let u;
33
+ o[2] === Symbol.for("react.memo_cache_sentinel") ? (u = /* @__PURE__ */ jsx(FileTabsBar, {}), o[2] = u) : u = o[2];
34
+ let d;
35
+ return o[3] !== s.fileContent || o[4] !== s.isContentLoading || o[5] !== s.selectedFile ? (d = /* @__PURE__ */ jsxs("div", {
35
36
  className: "flex h-full",
36
- children: [o, /* @__PURE__ */ jsxs("div", {
37
+ children: [l, /* @__PURE__ */ jsxs("div", {
37
38
  className: "flex min-w-0 flex-1 flex-col",
38
- children: [s, /* @__PURE__ */ jsx("div", {
39
+ children: [u, /* @__PURE__ */ jsx("div", {
39
40
  className: "flex-1 overflow-hidden p-3 pt-2",
40
41
  children: /* @__PURE__ */ jsx(FileContentViewer, {
41
- selectedFile: a.selectedFile,
42
- content: a.fileContent,
43
- isLoading: a.isContentLoading,
42
+ selectedFile: s.selectedFile,
43
+ content: s.fileContent,
44
+ isLoading: s.isContentLoading,
44
45
  className: "h-full"
45
46
  })
46
47
  })]
47
48
  })]
48
- }), i[3] = a.fileContent, i[4] = a.isContentLoading, i[5] = a.selectedFile, i[6] = p) : p = i[6], p;
49
+ }), o[3] = s.fileContent, o[4] = s.isContentLoading, o[5] = s.selectedFile, o[6] = d) : d = o[6], d;
49
50
  }
50
51
  function FileExplorerPanel(e) {
51
- let l = c(26), { variant: u, featureId: d, title: f, description: m, workspaceId: h } = e, { closePanel: g, panelSize: _, setPanelSize: v, environments: y } = useWorkbenchLayout(), b = useFeatureConfig(d), x;
52
- l[0] === b?.config?.environments ? x = l[1] : (x = b?.config?.environments ?? [], l[0] = b?.config?.environments, l[1] = x);
53
- let S = x, C = y?.[0]?.slotId ?? "", w;
54
- l[2] !== S || l[3] !== C ? (w = S.length === 0 || S.includes(C), l[2] = S, l[3] = C, l[4] = w) : w = l[4];
55
- let T = w;
56
- if (!T) {
57
- let e;
58
- l[5] === Symbol.for("react.memo_cache_sentinel") ? (e = /* @__PURE__ */ jsx(Files, { className: "h-4 w-4" }), l[5] = e) : e = l[5];
59
- let i;
60
- l[6] === Symbol.for("react.memo_cache_sentinel") ? (i = /* @__PURE__ */ jsx("div", {
61
- className: "flex flex-1 items-center justify-center p-4",
62
- children: /* @__PURE__ */ jsx("p", {
63
- className: "text-muted-foreground text-sm",
64
- children: "File explorer is not available for this environment."
65
- })
66
- }), l[6] = i) : i = l[6];
67
- let a;
68
- return l[7] !== g || l[8] !== m || l[9] !== _ || l[10] !== v || l[11] !== f ? (a = /* @__PURE__ */ jsx(SidebarPanel, {
69
- icon: e,
70
- title: f,
71
- description: m,
72
- size: _,
73
- onSizeChange: v,
74
- onClose: g,
75
- children: i
76
- }), l[7] = g, l[8] = m, l[9] = _, l[10] = v, l[11] = f, l[12] = a) : a = l[12], a;
77
- }
78
- let E;
79
- l[13] === Symbol.for("react.memo_cache_sentinel") ? (E = /* @__PURE__ */ jsx(Files, { className: "h-4 w-4" }), l[13] = E) : E = l[13];
80
- let D;
81
- l[14] === Symbol.for("react.memo_cache_sentinel") ? (D = /* @__PURE__ */ jsx(FileExplorerContent, {}), l[14] = D) : D = l[14];
82
- let O;
83
- l[15] !== T || l[16] !== u || l[17] !== h ? (O = /* @__PURE__ */ jsx(FileExplorerProvider, {
84
- variant: u,
85
- workspaceId: h,
86
- enabled: T,
87
- children: D
88
- }), l[15] = T, l[16] = u, l[17] = h, l[18] = O) : O = l[18];
89
- let k;
90
- return l[19] !== g || l[20] !== m || l[21] !== _ || l[22] !== v || l[23] !== O || l[24] !== f ? (k = /* @__PURE__ */ jsx(SidebarPanel, {
91
- icon: E,
92
- title: f,
93
- description: m,
94
- size: _,
95
- onSizeChange: v,
96
- onClose: g,
97
- children: O
98
- }), l[19] = g, l[20] = m, l[21] = _, l[22] = v, l[23] = O, l[24] = f, l[25] = k) : k = l[25], k;
52
+ let f = c(24), { variant: p, featureId: m, title: h, description: g, workspaceId: _ } = e, { closePanel: v, panelSize: y, setPanelSize: b, environments: x, selectedSlotId: S } = useWorkbenchLayout(), C = useFeatureConfig(m), w;
53
+ f[0] === C?.config?.environments ? w = f[1] : (w = C?.config?.environments ?? [], f[0] = C?.config?.environments, f[1] = w);
54
+ let T = w, E;
55
+ f[2] !== x || f[3] !== S ? (E = x?.find((e) => e.slotId === S), f[2] = x, f[3] = S, f[4] = E) : E = f[4];
56
+ let D = E, O;
57
+ f[5] !== T || f[6] !== S ? (O = T.length === 0 || T.includes(S), f[5] = T, f[6] = S, f[7] = O) : O = f[7];
58
+ let k = O, A = !D || D.status === "running", j = k && A, M;
59
+ f[8] === Symbol.for("react.memo_cache_sentinel") ? (M = /* @__PURE__ */ jsx(Files, { className: "h-4 w-4" }), f[8] = M) : M = f[8];
60
+ let N;
61
+ f[9] === Symbol.for("react.memo_cache_sentinel") ? (N = /* @__PURE__ */ jsx(EnvironmentSelector, {}), f[9] = N) : N = f[9];
62
+ let P;
63
+ f[10] !== k || f[11] !== j || f[12] !== A || f[13] !== S || f[14] !== p || f[15] !== _ ? (P = k ? A ? /* @__PURE__ */ jsx(FileExplorerProvider, {
64
+ variant: p,
65
+ workspaceId: _,
66
+ slotId: S || void 0,
67
+ enabled: j,
68
+ children: /* @__PURE__ */ jsx(FileExplorerContent, {})
69
+ }) : /* @__PURE__ */ jsx("div", {
70
+ className: "flex flex-1 items-center justify-center p-4",
71
+ children: /* @__PURE__ */ jsx("p", {
72
+ className: "text-muted-foreground text-sm",
73
+ children: "This environment is not available (stopped)."
74
+ })
75
+ }) : /* @__PURE__ */ jsx("div", {
76
+ className: "flex flex-1 items-center justify-center p-4",
77
+ children: /* @__PURE__ */ jsx("p", {
78
+ className: "text-muted-foreground text-sm",
79
+ children: "File explorer is not available for this environment."
80
+ })
81
+ }), f[10] = k, f[11] = j, f[12] = A, f[13] = S, f[14] = p, f[15] = _, f[16] = P) : P = f[16];
82
+ let F;
83
+ return f[17] !== v || f[18] !== g || f[19] !== y || f[20] !== b || f[21] !== P || f[22] !== h ? (F = /* @__PURE__ */ jsxs(SidebarPanel, {
84
+ icon: M,
85
+ title: h,
86
+ description: g,
87
+ size: y,
88
+ onSizeChange: b,
89
+ onClose: v,
90
+ children: [N, P]
91
+ }), f[17] = v, f[18] = g, f[19] = y, f[20] = b, f[21] = P, f[22] = h, f[23] = F) : F = f[23], F;
99
92
  }
100
93
  function LocalFileExplorerPanel(e) {
101
- let i = c(2), { workspaceId: a } = e, o;
102
- return i[0] === a ? o = i[1] : (o = /* @__PURE__ */ jsx(FileExplorerPanel, {
94
+ let o = c(2), { workspaceId: s } = e, l;
95
+ return o[0] === s ? l = o[1] : (l = /* @__PURE__ */ jsx(FileExplorerPanel, {
103
96
  variant: "local",
104
97
  featureId: "localFileExplorer",
105
98
  title: "Files",
106
99
  description: "Browse and view local project files.",
107
- workspaceId: a
108
- }), i[0] = a, i[1] = o), o;
100
+ workspaceId: s
101
+ }), o[0] = s, o[1] = l), l;
109
102
  }
110
103
  function RemoteFileExplorerPanel(e) {
111
- let i = c(2), { workspaceId: a } = e, o;
112
- return i[0] === a ? o = i[1] : (o = /* @__PURE__ */ jsx(FileExplorerPanel, {
104
+ let o = c(2), { workspaceId: s } = e, l;
105
+ return o[0] === s ? l = o[1] : (l = /* @__PURE__ */ jsx(FileExplorerPanel, {
113
106
  variant: "remote",
114
107
  featureId: "remoteFileExplorer",
115
108
  title: "Remote Files",
116
109
  description: "Browse and view files on the remote workspace.",
117
- workspaceId: a
118
- }), i[0] = a, i[1] = o), o;
110
+ workspaceId: s
111
+ }), o[0] = s, o[1] = l), l;
119
112
  }
120
113
  export { LocalFileExplorerPanel, RemoteFileExplorerPanel };
@@ -14,38 +14,42 @@ function fileTreeKey(e, n, r) {
14
14
  ...r ? [r] : []
15
15
  ];
16
16
  }
17
- function useFileTree(i, o, s) {
18
- let l = c(12), u = s === void 0 ? !0 : s, d = useLoopstackClient(), f;
19
- l[0] !== d.envKey || l[1] !== i || l[2] !== o ? (f = fileTreeKey(d.envKey, i, o), l[0] = d.envKey, l[1] = i, l[2] = o, l[3] = f) : f = l[3];
20
- let p;
21
- l[4] !== d.http || l[5] !== i || l[6] !== o ? (p = () => d.http.get(`${explorerPath(i, o)}/tree`), l[4] = d.http, l[5] = i, l[6] = o, l[7] = p) : p = l[7];
22
- let m = !!o && u, h;
23
- return l[8] !== f || l[9] !== p || l[10] !== m ? (h = {
24
- queryKey: f,
25
- queryFn: p,
26
- enabled: m,
17
+ function useFileTree(i, o, s, l) {
18
+ let u = c(14), d = l === void 0 ? !0 : l, f = useLoopstackClient(), p;
19
+ u[0] !== f.envKey || u[1] !== s || u[2] !== i || u[3] !== o ? (p = [...fileTreeKey(f.envKey, i, o), s ?? ""], u[0] = f.envKey, u[1] = s, u[2] = i, u[3] = o, u[4] = p) : p = u[4];
20
+ let m;
21
+ u[5] !== f.http || u[6] !== s || u[7] !== i || u[8] !== o ? (m = () => f.http.get(`${explorerPath(i, o)}/tree`, s ? { slotId: s } : void 0), u[5] = f.http, u[6] = s, u[7] = i, u[8] = o, u[9] = m) : m = u[9];
22
+ let h = !!o && d, g;
23
+ return u[10] !== p || u[11] !== m || u[12] !== h ? (g = {
24
+ queryKey: p,
25
+ queryFn: m,
26
+ enabled: h,
27
27
  staleTime: 3e4,
28
28
  retry: !1
29
- }, l[8] = f, l[9] = p, l[10] = m, l[11] = h) : h = l[11], useQuery(h);
29
+ }, u[10] = p, u[11] = m, u[12] = h, u[13] = g) : g = u[13], useQuery(g);
30
30
  }
31
- function useFileContent(i, a, o, s) {
32
- let l = c(14), u = s === void 0 ? !0 : s, d = useLoopstackClient(), f;
33
- l[0] !== d.envKey || l[1] !== o || l[2] !== i || l[3] !== a ? (f = [
31
+ function useFileContent(i, a, o, s, l) {
32
+ let u = c(16), d = l === void 0 ? !0 : l, f = useLoopstackClient(), p = s ?? "", m;
33
+ u[0] !== f.envKey || u[1] !== o || u[2] !== p || u[3] !== i || u[4] !== a ? (m = [
34
34
  "file-explorer-content",
35
- d.envKey,
35
+ f.envKey,
36
36
  i,
37
37
  a,
38
- o
39
- ], l[0] = d.envKey, l[1] = o, l[2] = i, l[3] = a, l[4] = f) : f = l[4];
40
- let p;
41
- l[5] !== d.http || l[6] !== o || l[7] !== i || l[8] !== a ? (p = () => d.http.get(`${explorerPath(i, a)}/read`, { path: o }), l[5] = d.http, l[6] = o, l[7] = i, l[8] = a, l[9] = p) : p = l[9];
42
- let m = !!a && !!o && u, h;
43
- return l[10] !== f || l[11] !== p || l[12] !== m ? (h = {
44
- queryKey: f,
45
- queryFn: p,
46
- enabled: m,
38
+ o,
39
+ p
40
+ ], u[0] = f.envKey, u[1] = o, u[2] = p, u[3] = i, u[4] = a, u[5] = m) : m = u[5];
41
+ let h;
42
+ u[6] !== f.http || u[7] !== o || u[8] !== s || u[9] !== i || u[10] !== a ? (h = () => f.http.get(`${explorerPath(i, a)}/read`, {
43
+ path: o,
44
+ ...s ? { slotId: s } : {}
45
+ }), u[6] = f.http, u[7] = o, u[8] = s, u[9] = i, u[10] = a, u[11] = h) : h = u[11];
46
+ let g = !!a && !!o && d, _;
47
+ return u[12] !== m || u[13] !== h || u[14] !== g ? (_ = {
48
+ queryKey: m,
49
+ queryFn: h,
50
+ enabled: g,
47
51
  staleTime: 15e3,
48
52
  retry: !1
49
- }, l[10] = f, l[11] = p, l[12] = m, l[13] = h) : h = l[13], useQuery(h);
53
+ }, u[12] = m, u[13] = h, u[14] = g, u[15] = _) : _ = u[15], useQuery(_);
50
54
  }
51
55
  export { fileTreeKey, useFileContent, useFileTree };
@@ -6,78 +6,78 @@ import { createContext, useCallback, useContext, useMemo, useState } from "react
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  import { useQueryClient } from "@tanstack/react-query";
8
8
  var FileExplorerContext = createContext(null);
9
- function FileExplorerProvider(u) {
10
- let d = c(37), { variant: f, workspaceId: p, enabled: m, children: h } = u, g = m === void 0 ? !0 : m, _ = useLoopstackClient(), v = useQueryClient(), y;
11
- d[0] === Symbol.for("react.memo_cache_sentinel") ? (y = /* @__PURE__ */ new Set(), d[0] = y) : y = d[0];
9
+ function FileExplorerProvider(l) {
10
+ let u = c(37), { variant: d, workspaceId: f, slotId: p, enabled: m, children: h } = l, g = m === void 0 ? !0 : m, _ = useLoopstackClient(), v = useQueryClient(), y;
11
+ u[0] === Symbol.for("react.memo_cache_sentinel") ? (y = /* @__PURE__ */ new Set(), u[0] = y) : y = u[0];
12
12
  let [b, x] = useState(y), S;
13
- d[1] === Symbol.for("react.memo_cache_sentinel") ? (S = [], d[1] = S) : S = d[1];
14
- let [C, w] = useState(S), [T, E] = useState(null), D = useFileTree(f, p, g), O = useFileContent(f, p, T?.type === "file" ? T.path : void 0, g), k;
15
- d[2] === Symbol.for("react.memo_cache_sentinel") ? (k = (e) => {
16
- x((o) => {
17
- let s = new Set(o);
18
- return s.has(e) ? s.delete(e) : s.add(e), s;
13
+ u[1] === Symbol.for("react.memo_cache_sentinel") ? (S = [], u[1] = S) : S = u[1];
14
+ let [C, w] = useState(S), [T, E] = useState(null), D = useFileTree(d, f, p, g), O = useFileContent(d, f, T?.type === "file" ? T.path : void 0, p, g), k;
15
+ u[2] === Symbol.for("react.memo_cache_sentinel") ? (k = (e) => {
16
+ x((a) => {
17
+ let o = new Set(a);
18
+ return o.has(e) ? o.delete(e) : o.add(e), o;
19
19
  });
20
- }, d[2] = k) : k = d[2];
20
+ }, u[2] = k) : k = u[2];
21
21
  let A = k, j;
22
- d[3] === Symbol.for("react.memo_cache_sentinel") ? (j = (e) => {
23
- e.type === "file" && (E(e), w((o) => o.some((o) => o.path === e.path) ? o : [...o, e]));
24
- }, d[3] = j) : j = d[3];
22
+ u[3] === Symbol.for("react.memo_cache_sentinel") ? (j = (e) => {
23
+ e.type === "file" && (E(e), w((a) => a.some((a) => a.path === e.path) ? a : [...a, e]));
24
+ }, u[3] = j) : j = u[3];
25
25
  let M = j, N;
26
- d[4] === T?.path ? N = d[5] : (N = (e) => {
27
- w((o) => {
28
- let s = o.filter((o) => o.path !== e.path);
29
- if (T?.path === e.path) if (s.length > 0) {
30
- let l = o.findIndex((o) => o.path === e.path);
31
- E(s[Math.max(0, l - 1)]);
26
+ u[4] === T?.path ? N = u[5] : (N = (e) => {
27
+ w((a) => {
28
+ let o = a.filter((a) => a.path !== e.path);
29
+ if (T?.path === e.path) if (o.length > 0) {
30
+ let s = a.findIndex((a) => a.path === e.path);
31
+ E(o[Math.max(0, s - 1)]);
32
32
  } else E(null);
33
- return s;
33
+ return o;
34
34
  });
35
- }, d[4] = T?.path, d[5] = N);
35
+ }, u[4] = T?.path, u[5] = N);
36
36
  let P = N, F;
37
- d[6] === T ? F = d[7] : (F = () => {
37
+ u[6] === T ? F = u[7] : (F = () => {
38
38
  T && w((e) => {
39
- let o = e.filter((e) => e.path !== T.path);
40
- if (o.length > 0) {
41
- let s = e.findIndex((e) => e.path === T.path);
42
- E(o[Math.max(0, s - 1)]);
39
+ let a = e.filter((e) => e.path !== T.path);
40
+ if (a.length > 0) {
41
+ let o = e.findIndex((e) => e.path === T.path);
42
+ E(a[Math.max(0, o - 1)]);
43
43
  } else E(null);
44
- return o;
44
+ return a;
45
45
  });
46
- }, d[6] = T, d[7] = F);
46
+ }, u[6] = T, u[7] = F);
47
47
  let I = F, L;
48
- d[8] === Symbol.for("react.memo_cache_sentinel") ? (L = () => {
48
+ u[8] === Symbol.for("react.memo_cache_sentinel") ? (L = () => {
49
49
  w([]), E(null);
50
- }, d[8] = L) : L = d[8];
50
+ }, u[8] = L) : L = u[8];
51
51
  let R = L, z;
52
- d[9] === Symbol.for("react.memo_cache_sentinel") ? (z = (e) => {
52
+ u[9] === Symbol.for("react.memo_cache_sentinel") ? (z = (e) => {
53
53
  w([e]), E(e);
54
- }, d[9] = z) : z = d[9];
54
+ }, u[9] = z) : z = u[9];
55
55
  let B = z, V;
56
- d[10] === T ? V = d[11] : (V = (e) => {
57
- w((o) => {
58
- let s = o.findIndex((o) => o.path === e.path);
59
- if (s <= 0) return o;
60
- let l = o.slice(s);
61
- return T && o.findIndex((e) => e.path === T.path) < s && E(e), l;
56
+ u[10] === T ? V = u[11] : (V = (e) => {
57
+ w((a) => {
58
+ let o = a.findIndex((a) => a.path === e.path);
59
+ if (o <= 0) return a;
60
+ let s = a.slice(o);
61
+ return T && a.findIndex((e) => e.path === T.path) < o && E(e), s;
62
62
  });
63
- }, d[10] = T, d[11] = V);
63
+ }, u[10] = T, u[11] = V);
64
64
  let H = V, U;
65
- d[12] === T ? U = d[13] : (U = (e) => {
66
- w((o) => {
67
- let s = o.findIndex((o) => o.path === e.path);
68
- if (s < 0 || s >= o.length - 1) return o;
69
- let l = o.slice(0, s + 1);
70
- return T && o.findIndex((e) => e.path === T.path) > s && E(e), l;
65
+ u[12] === T ? U = u[13] : (U = (e) => {
66
+ w((a) => {
67
+ let o = a.findIndex((a) => a.path === e.path);
68
+ if (o < 0 || o >= a.length - 1) return a;
69
+ let s = a.slice(0, o + 1);
70
+ return T && a.findIndex((e) => e.path === T.path) > o && E(e), s;
71
71
  });
72
- }, d[12] = T, d[13] = U);
72
+ }, u[12] = T, u[13] = U);
73
73
  let W = U, G;
74
- d[14] !== _.envKey || d[15] !== v ? (G = () => {
74
+ u[14] !== _.envKey || u[15] !== v ? (G = () => {
75
75
  v.invalidateQueries({ queryKey: fileTreeKey(_.envKey) });
76
- }, d[14] = _.envKey, d[15] = v, d[16] = G) : G = d[16];
76
+ }, u[14] = _.envKey, u[15] = v, u[16] = G) : G = u[16];
77
77
  let K = G, q;
78
- d[17] === D.data ? q = d[18] : (q = D.data ?? [], d[17] = D.data, d[18] = q);
78
+ u[17] === D.data ? q = u[18] : (q = D.data ?? [], u[17] = D.data, u[18] = q);
79
79
  let J = D.isLoading && !D.data, Y = O.data?.content ?? null, X = O.isLoading && !!T, Z;
80
- d[19] !== I || d[20] !== P || d[21] !== H || d[22] !== W || d[23] !== b || d[24] !== C || d[25] !== K || d[26] !== T || d[27] !== q || d[28] !== J || d[29] !== Y || d[30] !== X || d[31] !== D.error || d[32] !== D.isFetching ? (Z = {
80
+ u[19] !== I || u[20] !== P || u[21] !== H || u[22] !== W || u[23] !== b || u[24] !== C || u[25] !== K || u[26] !== T || u[27] !== q || u[28] !== J || u[29] !== Y || u[30] !== X || u[31] !== D.error || u[32] !== D.isFetching ? (Z = {
81
81
  nodes: q,
82
82
  isTreeLoading: J,
83
83
  treeError: D.error,
@@ -96,12 +96,12 @@ function FileExplorerProvider(u) {
96
96
  closeToRight: W,
97
97
  clearSelection: I,
98
98
  refreshTree: K
99
- }, d[19] = I, d[20] = P, d[21] = H, d[22] = W, d[23] = b, d[24] = C, d[25] = K, d[26] = T, d[27] = q, d[28] = J, d[29] = Y, d[30] = X, d[31] = D.error, d[32] = D.isFetching, d[33] = Z) : Z = d[33];
99
+ }, u[19] = I, u[20] = P, u[21] = H, u[22] = W, u[23] = b, u[24] = C, u[25] = K, u[26] = T, u[27] = q, u[28] = J, u[29] = Y, u[30] = X, u[31] = D.error, u[32] = D.isFetching, u[33] = Z) : Z = u[33];
100
100
  let Q = Z, $;
101
- return d[34] !== h || d[35] !== Q ? ($ = /* @__PURE__ */ jsx(FileExplorerContext.Provider, {
101
+ return u[34] !== h || u[35] !== Q ? ($ = /* @__PURE__ */ jsx(FileExplorerContext.Provider, {
102
102
  value: Q,
103
103
  children: h
104
- }), d[34] = h, d[35] = Q, d[36] = $) : $ = d[36], $;
104
+ }), u[34] = h, u[35] = Q, u[36] = $) : $ = u[36], $;
105
105
  }
106
106
  function useFileExplorer() {
107
107
  let e = useContext(FileExplorerContext);
@@ -5,6 +5,7 @@ import "../../../hooks/useProcessor.js";
5
5
  import { useWorkbenchLayout } from "../../workbench/providers/WorkbenchLayoutProvider.js";
6
6
  import { SidebarPanel } from "../../workbench/components/SidebarPanel.js";
7
7
  import "../../workbench/index.js";
8
+ import { EnvironmentSelector } from "../../workbench/components/EnvironmentSelector.js";
8
9
  import { useGitInvalidation, useGitLog, useGitRemote, useGitStatus, useRemoveGitRemote } from "../hooks/useGit.js";
9
10
  import { GitBranchBadge } from "./GitBranchBadge.js";
10
11
  import { GitCommitList } from "./GitCommitList.js";
@@ -12,31 +13,33 @@ import { GitRemoteStatus } from "./GitRemoteStatus.js";
12
13
  import { c } from "react/compiler-runtime";
13
14
  import { jsx, jsxs } from "react/jsx-runtime";
14
15
  import { GitBranch, Loader2 } from "lucide-react";
15
- function WorkbenchGitPanel(y) {
16
- let b = c(20), { workspaceId: x } = y, { panelSize: S, setPanelSize: C, closePanel: w } = useWorkbenchLayout(), { router: T } = useStudio(), { data: E, isLoading: D } = useGitStatus(x), { data: O, isLoading: k } = useGitLog(x), { data: A } = useGitRemote(x);
17
- useGitInvalidation(x);
18
- let j = useCreateWorkflow(), M = useRunWorkflow(), N = useRemoveGitRemote(), P = j.isPending || M.isPending, F;
19
- b[0] !== j || b[1] !== T || b[2] !== M || b[3] !== x ? (F = () => {
20
- x && j.mutate({
16
+ function WorkbenchGitPanel(b) {
17
+ let x = c(21), { workspaceId: S } = b, { panelSize: C, setPanelSize: w, closePanel: T, selectedSlotId: E } = useWorkbenchLayout(), { router: D } = useStudio(), { data: O, isLoading: k } = useGitStatus(S, E), { data: A, isLoading: j } = useGitLog(S, 50, E), { data: M } = useGitRemote(S, E);
18
+ useGitInvalidation(S);
19
+ let N = useCreateWorkflow(), P = useRunWorkflow(), F = useRemoveGitRemote(), I = N.isPending || P.isPending, L;
20
+ x[0] !== N || x[1] !== D || x[2] !== P || x[3] !== S ? (L = () => {
21
+ S && N.mutate({
21
22
  workflowName: "connectGitHub",
22
23
  title: null,
23
- workspaceId: x,
24
+ workspaceId: S,
24
25
  transition: null,
25
26
  args: {}
26
27
  }, { onSuccess: (t) => {
27
- M.mutate({ workflowId: t.id }, { onSuccess: () => {
28
- T.navigateToWorkflow(t.id);
28
+ P.mutate({ workflowId: t.id }, { onSuccess: () => {
29
+ D.navigateToWorkflow(t.id);
29
30
  } });
30
31
  } });
31
- }, b[0] = j, b[1] = T, b[2] = M, b[3] = x, b[4] = F) : F = b[4];
32
- let I = F, L = D || k, R;
33
- b[5] === Symbol.for("react.memo_cache_sentinel") ? (R = /* @__PURE__ */ jsx(GitBranch, { className: "h-4 w-4" }), b[5] = R) : R = b[5];
34
- let z;
35
- b[6] !== I || b[7] !== P || b[8] !== L || b[9] !== O?.commits || b[10] !== A || b[11] !== N || b[12] !== E || b[13] !== x ? (z = /* @__PURE__ */ jsx("div", {
32
+ }, x[0] = N, x[1] = D, x[2] = P, x[3] = S, x[4] = L) : L = x[4];
33
+ let R = L, z = k || j, B;
34
+ x[5] === Symbol.for("react.memo_cache_sentinel") ? (B = /* @__PURE__ */ jsx(GitBranch, { className: "h-4 w-4" }), x[5] = B) : B = x[5];
35
+ let V;
36
+ x[6] === Symbol.for("react.memo_cache_sentinel") ? (V = /* @__PURE__ */ jsx(EnvironmentSelector, {}), x[6] = V) : V = x[6];
37
+ let H;
38
+ x[7] !== R || x[8] !== I || x[9] !== z || x[10] !== A?.commits || x[11] !== M || x[12] !== F || x[13] !== O || x[14] !== S ? (H = /* @__PURE__ */ jsxs("div", {
36
39
  className: "flex h-full flex-col",
37
- children: /* @__PURE__ */ jsx("div", {
40
+ children: [V, /* @__PURE__ */ jsx("div", {
38
41
  className: "flex-1 overflow-y-auto px-4 py-3",
39
- children: L ? /* @__PURE__ */ jsxs("div", {
42
+ children: z ? /* @__PURE__ */ jsxs("div", {
40
43
  className: "flex items-center gap-2 py-4",
41
44
  children: [/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }), /* @__PURE__ */ jsx("span", {
42
45
  className: "text-muted-foreground text-sm",
@@ -45,34 +48,34 @@ function WorkbenchGitPanel(y) {
45
48
  }) : /* @__PURE__ */ jsxs("div", {
46
49
  className: "space-y-4",
47
50
  children: [
48
- E && /* @__PURE__ */ jsx(GitBranchBadge, { status: E }),
51
+ O && /* @__PURE__ */ jsx(GitBranchBadge, { status: O }),
49
52
  /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h4", {
50
53
  className: "mb-2 text-xs font-medium uppercase text-muted-foreground",
51
54
  children: "Remote"
52
55
  }), /* @__PURE__ */ jsx(GitRemoteStatus, {
53
- remote: A,
54
- onConnect: I,
55
- isConnecting: P,
56
- onRemove: x ? () => N.mutate({ workspaceId: x }) : void 0,
57
- isRemoving: N.isPending
56
+ remote: M,
57
+ onConnect: R,
58
+ isConnecting: I,
59
+ onRemove: S ? () => F.mutate({ workspaceId: S }) : void 0,
60
+ isRemoving: F.isPending
58
61
  })] }),
59
62
  /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h4", {
60
63
  className: "mb-2 text-xs font-medium uppercase text-muted-foreground",
61
64
  children: "Recent Commits"
62
- }), /* @__PURE__ */ jsx(GitCommitList, { commits: O?.commits ?? [] })] })
65
+ }), /* @__PURE__ */ jsx(GitCommitList, { commits: A?.commits ?? [] })] })
63
66
  ]
64
67
  })
65
- })
66
- }), b[6] = I, b[7] = P, b[8] = L, b[9] = O?.commits, b[10] = A, b[11] = N, b[12] = E, b[13] = x, b[14] = z) : z = b[14];
67
- let B;
68
- return b[15] !== w || b[16] !== S || b[17] !== C || b[18] !== z ? (B = /* @__PURE__ */ jsx(SidebarPanel, {
69
- icon: R,
68
+ })]
69
+ }), x[7] = R, x[8] = I, x[9] = z, x[10] = A?.commits, x[11] = M, x[12] = F, x[13] = O, x[14] = S, x[15] = H) : H = x[15];
70
+ let U;
71
+ return x[16] !== T || x[17] !== C || x[18] !== w || x[19] !== H ? (U = /* @__PURE__ */ jsx(SidebarPanel, {
72
+ icon: B,
70
73
  title: "Git",
71
74
  description: "Source control for this workspace.",
72
- size: S,
73
- onSizeChange: C,
74
- onClose: w,
75
- children: z
76
- }), b[15] = w, b[16] = S, b[17] = C, b[18] = z, b[19] = B) : B = b[19], B;
75
+ size: C,
76
+ onSizeChange: w,
77
+ onClose: T,
78
+ children: H
79
+ }), x[16] = T, x[17] = C, x[18] = w, x[19] = H, x[20] = U) : U = x[20], U;
77
80
  }
78
81
  export { WorkbenchGitPanel };
@@ -6,47 +6,50 @@ import { c } from "react/compiler-runtime";
6
6
  import { useEffect } from "react";
7
7
  import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
8
8
  var gitPath = (e) => `/api/v1/workspaces/${e}/git`;
9
- function useGitStatus(r) {
10
- let i = c(10), o = useLoopstackClient(), l;
11
- i[0] !== o.envKey || i[1] !== r ? (l = queryKeys.gitStatus(o.envKey, r), i[0] = o.envKey, i[1] = r, i[2] = l) : l = i[2];
12
- let u;
13
- i[3] !== o.http || i[4] !== r ? (u = () => o.http.get(`${gitPath(r)}/status`), i[3] = o.http, i[4] = r, i[5] = u) : u = i[5];
14
- let d = !!r, f;
15
- return i[6] !== l || i[7] !== u || i[8] !== d ? (f = {
16
- queryKey: l,
17
- queryFn: u,
18
- enabled: d,
9
+ function useGitStatus(r, i) {
10
+ let o = c(12), l = useLoopstackClient(), u;
11
+ o[0] !== l.envKey || o[1] !== i || o[2] !== r ? (u = [...queryKeys.gitStatus(l.envKey, r), i ?? ""], o[0] = l.envKey, o[1] = i, o[2] = r, o[3] = u) : u = o[3];
12
+ let d;
13
+ o[4] !== l.http || o[5] !== i || o[6] !== r ? (d = () => l.http.get(`${gitPath(r)}/status`, i ? { slotId: i } : void 0), o[4] = l.http, o[5] = i, o[6] = r, o[7] = d) : d = o[7];
14
+ let f = !!r, p;
15
+ return o[8] !== u || o[9] !== d || o[10] !== f ? (p = {
16
+ queryKey: u,
17
+ queryFn: d,
18
+ enabled: f,
19
19
  staleTime: 3e4,
20
20
  retry: !1
21
- }, i[6] = l, i[7] = u, i[8] = d, i[9] = f) : f = i[9], useQuery(f);
21
+ }, o[8] = u, o[9] = d, o[10] = f, o[11] = p) : p = o[11], useQuery(p);
22
22
  }
23
- function useGitLog(r, i) {
24
- let o = c(11), l = i === void 0 ? 50 : i, u = useLoopstackClient(), d;
25
- o[0] !== u.envKey || o[1] !== r ? (d = queryKeys.gitLog(u.envKey, r), o[0] = u.envKey, o[1] = r, o[2] = d) : d = o[2];
26
- let f;
27
- o[3] !== u.http || o[4] !== l || o[5] !== r ? (f = () => u.http.get(`${gitPath(r)}/log`, { limit: l }), o[3] = u.http, o[4] = l, o[5] = r, o[6] = f) : f = o[6];
28
- let p = !!r, m;
29
- return o[7] !== d || o[8] !== f || o[9] !== p ? (m = {
30
- queryKey: d,
31
- queryFn: f,
32
- enabled: p,
23
+ function useGitLog(r, i, o) {
24
+ let l = c(13), u = i === void 0 ? 50 : i, d = useLoopstackClient(), f;
25
+ l[0] !== d.envKey || l[1] !== o || l[2] !== r ? (f = [...queryKeys.gitLog(d.envKey, r), o ?? ""], l[0] = d.envKey, l[1] = o, l[2] = r, l[3] = f) : f = l[3];
26
+ let p;
27
+ l[4] !== d.http || l[5] !== u || l[6] !== o || l[7] !== r ? (p = () => d.http.get(`${gitPath(r)}/log`, {
28
+ limit: u,
29
+ ...o ? { slotId: o } : {}
30
+ }), l[4] = d.http, l[5] = u, l[6] = o, l[7] = r, l[8] = p) : p = l[8];
31
+ let m = !!r, h;
32
+ return l[9] !== f || l[10] !== p || l[11] !== m ? (h = {
33
+ queryKey: f,
34
+ queryFn: p,
35
+ enabled: m,
33
36
  staleTime: 3e4,
34
37
  retry: !1
35
- }, o[7] = d, o[8] = f, o[9] = p, o[10] = m) : m = o[10], useQuery(m);
38
+ }, l[9] = f, l[10] = p, l[11] = m, l[12] = h) : h = l[12], useQuery(h);
36
39
  }
37
- function useGitRemote(r) {
38
- let i = c(10), o = useLoopstackClient(), l;
39
- i[0] !== o.envKey || i[1] !== r ? (l = queryKeys.gitRemote(o.envKey, r), i[0] = o.envKey, i[1] = r, i[2] = l) : l = i[2];
40
- let u;
41
- i[3] !== o.http || i[4] !== r ? (u = () => o.http.get(`${gitPath(r)}/remote`), i[3] = o.http, i[4] = r, i[5] = u) : u = i[5];
42
- let d = !!r, f;
43
- return i[6] !== l || i[7] !== u || i[8] !== d ? (f = {
44
- queryKey: l,
45
- queryFn: u,
46
- enabled: d,
40
+ function useGitRemote(r, i) {
41
+ let o = c(12), l = useLoopstackClient(), u;
42
+ o[0] !== l.envKey || o[1] !== i || o[2] !== r ? (u = [...queryKeys.gitRemote(l.envKey, r), i ?? ""], o[0] = l.envKey, o[1] = i, o[2] = r, o[3] = u) : u = o[3];
43
+ let d;
44
+ o[4] !== l.http || o[5] !== i || o[6] !== r ? (d = () => l.http.get(`${gitPath(r)}/remote`, i ? { slotId: i } : void 0), o[4] = l.http, o[5] = i, o[6] = r, o[7] = d) : d = o[7];
45
+ let f = !!r, p;
46
+ return o[8] !== u || o[9] !== d || o[10] !== f ? (p = {
47
+ queryKey: u,
48
+ queryFn: d,
49
+ enabled: f,
47
50
  staleTime: 6e4,
48
51
  retry: !1
49
- }, i[6] = l, i[7] = u, i[8] = d, i[9] = f) : f = i[9], useQuery(f);
52
+ }, o[8] = u, o[9] = d, o[10] = f, o[11] = p) : p = o[11], useQuery(p);
50
53
  }
51
54
  function useGitInvalidation(i) {
52
55
  let a = c(5), s = useLoopstackClient(), l = useQueryClient(), u, d;
@@ -0,0 +1,46 @@
1
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../components/ui/select.js";
2
+ import { useWorkbenchLayout } from "../providers/WorkbenchLayoutProvider.js";
3
+ import { c } from "react/compiler-runtime";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ function EnvironmentSelector() {
6
+ let u = c(11), { environments: d, selectedSlotId: f, setSelectedSlotId: p } = useWorkbenchLayout(), m;
7
+ u[0] === d ? m = u[1] : (m = d ?? [], u[0] = d, u[1] = m);
8
+ let h = m;
9
+ if (h.length <= 1) return null;
10
+ let g;
11
+ u[2] === Symbol.for("react.memo_cache_sentinel") ? (g = /* @__PURE__ */ jsx(SelectTrigger, {
12
+ className: "h-7 text-xs",
13
+ children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select environment" })
14
+ }), u[2] = g) : g = u[2];
15
+ let _;
16
+ u[3] === h ? _ = u[4] : (_ = h.map(_temp), u[3] = h, u[4] = _);
17
+ let v;
18
+ u[5] === _ ? v = u[6] : (v = /* @__PURE__ */ jsx(SelectContent, { children: _ }), u[5] = _, u[6] = v);
19
+ let y;
20
+ return u[7] !== f || u[8] !== p || u[9] !== v ? (y = /* @__PURE__ */ jsx("div", {
21
+ className: "border-b px-3 py-2",
22
+ children: /* @__PURE__ */ jsxs(Select, {
23
+ value: f,
24
+ onValueChange: p,
25
+ children: [g, v]
26
+ })
27
+ }), u[7] = f, u[8] = p, u[9] = v, u[10] = y) : y = u[10], y;
28
+ }
29
+ function _temp(e) {
30
+ return /* @__PURE__ */ jsx(SelectItem, {
31
+ value: e.slotId,
32
+ className: "text-xs",
33
+ children: /* @__PURE__ */ jsxs("span", {
34
+ className: "flex items-center gap-2",
35
+ children: [
36
+ /* @__PURE__ */ jsx("span", { className: `h-1.5 w-1.5 rounded-full ${e.status === "running" ? "bg-green-500" : "bg-muted-foreground/40"}` }),
37
+ e.envName || e.slotId,
38
+ e.status !== "running" && /* @__PURE__ */ jsx("span", {
39
+ className: "text-muted-foreground",
40
+ children: "(stopped)"
41
+ })
42
+ ]
43
+ })
44
+ }, e.slotId);
45
+ }
46
+ export { EnvironmentSelector };
@@ -1,74 +1,83 @@
1
1
  import { useWorkspaceEnvironments } from "../../../hooks/useEnvironments.js";
2
2
  import { useOptionalStudioPreferences } from "../../../providers/StudioPreferencesProvider.js";
3
3
  import { c } from "react/compiler-runtime";
4
- import { createContext, useCallback, useContext, useMemo, useState } from "react";
4
+ import { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  var WorkbenchLayoutContext = createContext(null);
7
- function WorkbenchLayoutProvider(s) {
8
- let l = c(35), { children: u, workspaceId: d, workflow: f, getPreviewUrl: p, getEnvironmentPreviewUrl: m } = s, h = useOptionalStudioPreferences(), { data: g } = useWorkspaceEnvironments(d), [_, v] = useState(null), y;
9
- l[0] === Symbol.for("react.memo_cache_sentinel") ? (y = {}, l[0] = y) : y = l[0];
10
- let [b, x] = useState(y), S = h ? h.preferences.activePanel : _, C = h ? h.preferences.panelSizes : b, [w, T] = useState(null), [E, D] = useState(""), O;
11
- l[1] === g ? O = l[2] : (O = g === void 0 || g.some(_temp), l[1] = g, l[2] = O);
12
- let k = O, A;
13
- l[3] === Symbol.for("react.memo_cache_sentinel") ? (A = {
7
+ function WorkbenchLayoutProvider(u) {
8
+ let d = c(39), { children: f, workspaceId: p, workflow: m, getPreviewUrl: h, getEnvironmentPreviewUrl: g } = u, _ = useOptionalStudioPreferences(), { data: v } = useWorkspaceEnvironments(p), [y, b] = useState(null), x;
9
+ d[0] === Symbol.for("react.memo_cache_sentinel") ? (x = {}, d[0] = x) : x = d[0];
10
+ let [S, C] = useState(x), w = _ ? _.preferences.activePanel : y, T = _ ? _.preferences.panelSizes : S, [E, D] = useState(null), [O, k] = useState(""), A, j;
11
+ d[1] !== v || d[2] !== O ? (A = () => {
12
+ if (!v?.length) return;
13
+ let e = v.find((e) => e.slotId === O);
14
+ e?.status !== "running" && k((v.find(_temp) ?? e ?? v[0]).slotId);
15
+ }, j = [v, O], d[1] = v, d[2] = O, d[3] = A, d[4] = j) : (A = d[3], j = d[4]), useEffect(A, j);
16
+ let M;
17
+ d[5] === v ? M = d[6] : (M = v === void 0 || v.some(_temp2), d[5] = v, d[6] = M);
18
+ let N = M, P;
19
+ d[7] === Symbol.for("react.memo_cache_sentinel") ? (P = {
14
20
  runs: "medium",
15
21
  preview: "medium",
16
22
  files: "medium",
17
23
  environment: "small"
18
- }, l[3] = A) : A = l[3];
19
- let j = A, M = S ? C[S] ?? j[S] ?? "small" : "small", N;
20
- l[4] === h ? N = l[5] : (N = (e) => {
21
- h ? h.setPreference("activePanel", e) : v(e);
22
- }, l[4] = h, l[5] = N);
23
- let P = N, F;
24
- l[6] !== S || l[7] !== P ? (F = (e) => {
25
- P(S === e ? null : e);
26
- }, l[6] = S, l[7] = P, l[8] = F) : F = l[8];
27
- let I = F, L;
28
- l[9] === P ? L = l[10] : (L = () => {
29
- P(null);
30
- }, l[9] = P, l[10] = L);
24
+ }, d[7] = P) : P = d[7];
25
+ let F = P, I = w ? T[w] ?? F[w] ?? "small" : "small", L;
26
+ d[8] === _ ? L = d[9] : (L = (e) => {
27
+ _ ? _.setPreference("activePanel", e) : b(e);
28
+ }, d[8] = _, d[9] = L);
31
29
  let R = L, z;
32
- l[11] !== S || l[12] !== C || l[13] !== h ? (z = (e) => {
33
- if (!S) return;
34
- let o = {
35
- ...C,
36
- [S]: e
37
- };
38
- h ? h.setPreference("panelSizes", o) : x(o);
39
- }, l[11] = S, l[12] = C, l[13] = h, l[14] = z) : z = l[14];
30
+ d[10] !== w || d[11] !== R ? (z = (e) => {
31
+ R(w === e ? null : e);
32
+ }, d[10] = w, d[11] = R, d[12] = z) : z = d[12];
40
33
  let B = z, V;
41
- l[15] === P ? V = l[16] : (V = (e) => {
42
- D(e), P("preview");
43
- }, l[15] = P, l[16] = V);
34
+ d[13] === R ? V = d[14] : (V = () => {
35
+ R(null);
36
+ }, d[13] = R, d[14] = V);
44
37
  let H = V, U;
45
- l[17] !== S || l[18] !== w || l[19] !== R || l[20] !== g || l[21] !== m || l[22] !== p || l[23] !== H || l[24] !== M || l[25] !== k || l[26] !== E || l[27] !== B || l[28] !== I || l[29] !== f || l[30] !== d ? (U = {
46
- workspaceId: d,
47
- workflow: f,
48
- previewPanelEnabled: k,
49
- getPreviewUrl: p,
50
- getEnvironmentPreviewUrl: m,
51
- environments: g,
52
- activePanel: S,
53
- panelSize: M,
54
- togglePanel: I,
55
- closePanel: R,
56
- setPanelSize: B,
57
- selectedSlotId: E,
58
- setSelectedSlotId: D,
59
- openPreviewWithEnvironment: H,
60
- activeSectionId: w,
61
- setActiveSectionId: T
62
- }, l[17] = S, l[18] = w, l[19] = R, l[20] = g, l[21] = m, l[22] = p, l[23] = H, l[24] = M, l[25] = k, l[26] = E, l[27] = B, l[28] = I, l[29] = f, l[30] = d, l[31] = U) : U = l[31];
38
+ d[15] !== w || d[16] !== T || d[17] !== _ ? (U = (e) => {
39
+ if (!w) return;
40
+ let l = {
41
+ ...T,
42
+ [w]: e
43
+ };
44
+ _ ? _.setPreference("panelSizes", l) : C(l);
45
+ }, d[15] = w, d[16] = T, d[17] = _, d[18] = U) : U = d[18];
63
46
  let W = U, G;
64
- return l[32] !== u || l[33] !== W ? (G = /* @__PURE__ */ jsx(WorkbenchLayoutContext.Provider, {
65
- value: W,
66
- children: u
67
- }), l[32] = u, l[33] = W, l[34] = G) : G = l[34], G;
47
+ d[19] === R ? G = d[20] : (G = (e) => {
48
+ k(e), R("preview");
49
+ }, d[19] = R, d[20] = G);
50
+ let K = G, q;
51
+ d[21] !== w || d[22] !== E || d[23] !== H || d[24] !== v || d[25] !== g || d[26] !== h || d[27] !== K || d[28] !== I || d[29] !== N || d[30] !== O || d[31] !== W || d[32] !== B || d[33] !== m || d[34] !== p ? (q = {
52
+ workspaceId: p,
53
+ workflow: m,
54
+ previewPanelEnabled: N,
55
+ getPreviewUrl: h,
56
+ getEnvironmentPreviewUrl: g,
57
+ environments: v,
58
+ activePanel: w,
59
+ panelSize: I,
60
+ togglePanel: B,
61
+ closePanel: H,
62
+ setPanelSize: W,
63
+ selectedSlotId: O,
64
+ setSelectedSlotId: k,
65
+ openPreviewWithEnvironment: K,
66
+ activeSectionId: E,
67
+ setActiveSectionId: D
68
+ }, d[21] = w, d[22] = E, d[23] = H, d[24] = v, d[25] = g, d[26] = h, d[27] = K, d[28] = I, d[29] = N, d[30] = O, d[31] = W, d[32] = B, d[33] = m, d[34] = p, d[35] = q) : q = d[35];
69
+ let J = q, Y;
70
+ return d[36] !== f || d[37] !== J ? (Y = /* @__PURE__ */ jsx(WorkbenchLayoutContext.Provider, {
71
+ value: J,
72
+ children: f
73
+ }), d[36] = f, d[37] = J, d[38] = Y) : Y = d[38], Y;
68
74
  }
69
- function _temp(e) {
75
+ function _temp2(e) {
70
76
  return !!e.connectionUrl && (!!e.workerId || e.local);
71
77
  }
78
+ function _temp(e) {
79
+ return e.status === "running";
80
+ }
72
81
  function useWorkbenchLayout() {
73
82
  let e = useContext(WorkbenchLayoutContext);
74
83
  if (!e) throw Error("useWorkbenchLayout must be used within a WorkbenchLayoutProvider");
@@ -31,9 +31,22 @@ const UITextBlockSchema = z.object({
31
31
  UIServerToolUseBlockSchema,
32
32
  UIServerToolResultBlockSchema,
33
33
  UIToolResultBlockSchema
34
- ]), UIMessageSchema = z.object({
34
+ ]), UIUsageSchema = z.object({
35
+ inputTokens: z.number(),
36
+ outputTokens: z.number(),
37
+ cacheCreationInputTokens: z.number().optional(),
38
+ cacheReadInputTokens: z.number().optional(),
39
+ reasoningTokens: z.number().optional()
40
+ }), UIMessageMetaSchema = z.object({
41
+ model: z.string().optional(),
42
+ usage: UIUsageSchema.optional(),
43
+ costUsd: z.number().optional(),
44
+ numTurns: z.number().optional(),
45
+ durationMs: z.number().optional()
46
+ }), UIMessageSchema = z.object({
35
47
  role: z.enum(["user", "assistant"]),
36
48
  text: z.string().optional(),
37
- blocks: z.array(UIContentBlockSchema).optional()
49
+ blocks: z.array(UIContentBlockSchema).optional(),
50
+ meta: UIMessageMetaSchema.optional()
38
51
  });
39
52
  export { UIMessageSchema };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loopstack/loopstack-studio",
3
- "version": "0.36.0",
3
+ "version": "0.37.0",
4
4
  "repository": "loopstack-ai/loopstack-studio",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -26,9 +26,9 @@
26
26
  "dependencies": {
27
27
  "@fontsource/roboto": "^5.2.10",
28
28
  "@hookform/resolvers": "^5.2.2",
29
- "@loopstack/client": "^0.38.0",
30
- "@loopstack/contracts": "^0.38.0",
31
- "@loopstack/react": "^2.0.0",
29
+ "@loopstack/client": "^0.39.0",
30
+ "@loopstack/contracts": "^0.39.0",
31
+ "@loopstack/react": "^3.0.0",
32
32
  "@radix-ui/react-accordion": "^1.2.12",
33
33
  "@radix-ui/react-alert-dialog": "^1.1.15",
34
34
  "@radix-ui/react-avatar": "^1.1.11",