@loopstack/loopstack-studio 0.35.1 → 0.36.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.
- package/dist/features/documents/DocumentRenderer.js +7 -7
- package/dist/features/documents/renderers/DocumentFormRenderer.js +1 -1
- package/dist/features/oauth/OAuthCallbackPage.js +2 -0
- package/dist/features/run-view/RunView.js +153 -0
- package/dist/features/run-view/Transcript.js +127 -0
- package/dist/features/run-view/prompts/FormPrompt.js +129 -0
- package/dist/features/run-view/prompts/OAuthPrompt.js +94 -0
- package/dist/features/run-view/prompts/SandboxRunButton.js +35 -0
- package/dist/features/run-view/prompts/SecretPrompt.js +69 -0
- package/dist/features/run-view/prompts/SimplePrompts.js +196 -0
- package/dist/features/run-view/prompts/cards.js +90 -0
- package/dist/features/run-view/prompts/registry.js +16 -0
- package/dist/features/run-view/transcript.js +24 -0
- package/dist/features/run-view/useRunPrompts.js +111 -0
- package/dist/features/run-view/useRunTree.js +59 -0
- package/dist/features/run-view/useTreeLlmStreams.js +91 -0
- package/dist/features/secrets/components/WorkbenchSecretsPanel.js +1 -1
- package/dist/features/secrets/renderers/SecretInputRenderer.js +1 -1
- package/dist/features/workbench/WorkflowList.js +111 -52
- package/dist/features/workbench/components/NewRunDialog.js +1 -1
- package/dist/features/workbench/index.js +1 -1
- package/dist/features/workbench/providers/WorkbenchLayoutProvider.js +4 -1
- package/dist/features/workspaces/components/WorkspaceHomePage.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/node_modules/dompurify/dist/purify.es.js +351 -228
- package/dist/packages/client/dist/resources/workflows.js +2 -1
- package/dist/packages/client/dist/stream/invalidations.js +9 -2
- package/dist/packages/client/dist/stream/stream.js +73 -28
- package/dist/packages/contracts/dist/park-view/index.js +2 -0
- package/dist/packages/contracts/dist/park-view/park-view.rules.js +102 -0
- package/dist/packages/contracts/dist/park-view/park-view.types.js +15 -0
- package/dist/pages/PreviewWorkbenchPage.js +23 -23
- package/dist/providers/StudioPreferencesProvider.js +2 -1
- package/package.json +4 -4
|
@@ -7,7 +7,8 @@ function createWorkflowsResource(e) {
|
|
|
7
7
|
update: (t, n) => e.put(`/api/v1/workflows/${t}`, n),
|
|
8
8
|
delete: (t) => e.delete(`/api/v1/workflows/id/${t}`),
|
|
9
9
|
batchDelete: (t) => e.delete("/api/v1/workflows/batch", { ids: t }),
|
|
10
|
-
checkpoints: (t) => e.get(`/api/v1/workflows/${t}/checkpoints`)
|
|
10
|
+
checkpoints: (t) => e.get(`/api/v1/workflows/${t}/checkpoints`),
|
|
11
|
+
toolCalls: (t) => e.get(`/api/v1/workflows/${t}/tool-calls`)
|
|
11
12
|
};
|
|
12
13
|
}
|
|
13
14
|
export { createWorkflowsResource };
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { queryKeys } from "../queries/query-keys.js";
|
|
2
2
|
function resolveInvalidations(t, n) {
|
|
3
3
|
switch (t.type) {
|
|
4
|
-
case "workflow.created":
|
|
4
|
+
case "workflow.created": {
|
|
5
|
+
let r = [queryKeys.workflows(n)];
|
|
6
|
+
return t.parentId && r.push(queryKeys.childWorkflows(n, t.parentId)), r;
|
|
7
|
+
}
|
|
5
8
|
case "workflow.updated": {
|
|
6
|
-
let r = [
|
|
9
|
+
let r = [
|
|
10
|
+
queryKeys.workflow(n, t.id),
|
|
11
|
+
queryKeys.workflowStatus(n, t.id),
|
|
12
|
+
queryKeys.workflows(n)
|
|
13
|
+
];
|
|
7
14
|
return t.parentId && r.push(queryKeys.childWorkflows(n, t.parentId)), r;
|
|
8
15
|
}
|
|
9
16
|
case "document.created": return [queryKeys.documents(n, t.workflowId)];
|
|
@@ -3,6 +3,9 @@ import { ClientMessageSchema } from "../../../contracts/dist/events/client-messa
|
|
|
3
3
|
import "../../../contracts/dist/events/index.js";
|
|
4
4
|
import { createSseParser } from "./sse-parser.js";
|
|
5
5
|
var INITIAL_RETRY_DELAY_MS = 500;
|
|
6
|
+
function isFatalStreamStatus(e) {
|
|
7
|
+
return e >= 400 && e < 500 && e !== 408 && e !== 429;
|
|
8
|
+
}
|
|
6
9
|
function matchesWorkflow(e, t) {
|
|
7
10
|
return !t || e.type === "stream.reset" ? !0 : "workflowId" in e ? e.workflowId === t : !0;
|
|
8
11
|
}
|
|
@@ -11,6 +14,8 @@ var LoopstackStream = class {
|
|
|
11
14
|
handlers = /* @__PURE__ */ new Map();
|
|
12
15
|
anyHandlers = /* @__PURE__ */ new Set();
|
|
13
16
|
statusHandlers = /* @__PURE__ */ new Set();
|
|
17
|
+
errorHandlers = /* @__PURE__ */ new Set();
|
|
18
|
+
fatalError;
|
|
14
19
|
subscriberCount = 0;
|
|
15
20
|
abortController;
|
|
16
21
|
watchdog;
|
|
@@ -41,27 +46,47 @@ var LoopstackStream = class {
|
|
|
41
46
|
onStatus(e) {
|
|
42
47
|
return this.statusHandlers.add(e), () => this.statusHandlers.delete(e);
|
|
43
48
|
}
|
|
49
|
+
onError(e) {
|
|
50
|
+
return this.errorHandlers.add(e), this.fatalError && e(this.fatalError), () => this.errorHandlers.delete(e);
|
|
51
|
+
}
|
|
52
|
+
waitForOpen() {
|
|
53
|
+
return this.currentStatus === "open" ? Promise.resolve() : this.fatalError ? Promise.reject(this.fatalError) : new Promise((e, t) => {
|
|
54
|
+
let n = () => {
|
|
55
|
+
r(), i();
|
|
56
|
+
}, r = this.onStatus((r) => {
|
|
57
|
+
r === "open" ? (n(), e()) : (r === "closed" || r === "idle") && (n(), t(/* @__PURE__ */ Error("Event stream closed before it opened.")));
|
|
58
|
+
}), i = this.onError((e) => {
|
|
59
|
+
n(), t(e);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
}
|
|
44
63
|
events(e = {}) {
|
|
45
|
-
let t = [], n, r = !1,
|
|
64
|
+
let t = [], n, r = !1, i, o = this.onAny((r) => {
|
|
46
65
|
"userId" in r && matchesWorkflow(r, e.workflowId) && (t.push(r), n?.());
|
|
47
|
-
}),
|
|
48
|
-
|
|
66
|
+
}), s = this.onError((e) => {
|
|
67
|
+
i = e, n?.();
|
|
68
|
+
}), c = () => {
|
|
69
|
+
o(), s();
|
|
70
|
+
}, l = {
|
|
71
|
+
[Symbol.asyncIterator]: () => l,
|
|
49
72
|
next: async () => {
|
|
50
|
-
for (; t.length === 0 && !r;) await new Promise((e) => n = e), n = void 0;
|
|
51
|
-
|
|
52
|
-
done: !0,
|
|
53
|
-
value: void 0
|
|
54
|
-
} : {
|
|
73
|
+
for (; t.length === 0 && !r && !i;) await new Promise((e) => n = e), n = void 0;
|
|
74
|
+
if (t.length > 0) return {
|
|
55
75
|
done: !1,
|
|
56
76
|
value: t.shift()
|
|
57
77
|
};
|
|
78
|
+
if (c(), i) throw i;
|
|
79
|
+
return {
|
|
80
|
+
done: !0,
|
|
81
|
+
value: void 0
|
|
82
|
+
};
|
|
58
83
|
},
|
|
59
|
-
return: async () => (r = !0,
|
|
84
|
+
return: async () => (r = !0, c(), n?.(), {
|
|
60
85
|
done: !0,
|
|
61
86
|
value: void 0
|
|
62
87
|
})
|
|
63
88
|
};
|
|
64
|
-
return
|
|
89
|
+
return l;
|
|
65
90
|
}
|
|
66
91
|
close() {
|
|
67
92
|
this.closed = !0, this.handlers.clear(), this.anyHandlers.clear(), this.subscriberCount = 0, this.abortController?.abort(), this.clearWatchdog(), this.setStatus("closed");
|
|
@@ -83,37 +108,55 @@ var LoopstackStream = class {
|
|
|
83
108
|
return this.config.workflowId && e.searchParams.set("workflowId", this.config.workflowId), e;
|
|
84
109
|
}
|
|
85
110
|
async runLoop() {
|
|
86
|
-
this.running = !0;
|
|
87
|
-
let t = this.config.fetch ?? fetch,
|
|
111
|
+
this.running = !0, this.fatalError = void 0;
|
|
112
|
+
let t = this.config.fetch ?? fetch, a = 0;
|
|
88
113
|
for (; !this.closed && this.subscriberCount > 0;) {
|
|
89
114
|
this.abortController = new AbortController();
|
|
90
|
-
let { signal:
|
|
115
|
+
let { signal: o } = this.abortController;
|
|
91
116
|
try {
|
|
92
117
|
this.setStatus("connecting");
|
|
93
118
|
let r = { Accept: "text/event-stream" };
|
|
94
119
|
this.config.token && (r.Authorization = `Bearer ${this.config.token}`), this.lastEventId !== void 0 && (r["Last-Event-ID"] = this.lastEventId);
|
|
95
|
-
let
|
|
120
|
+
let s = await t(this.buildUrl(), {
|
|
96
121
|
headers: r,
|
|
97
122
|
credentials: this.config.credentials ?? "include",
|
|
98
|
-
signal:
|
|
123
|
+
signal: o
|
|
124
|
+
});
|
|
125
|
+
if (!s.ok) {
|
|
126
|
+
let t = new LoopstackApiError(s.status, void 0, `Event stream failed with status ${s.status}`);
|
|
127
|
+
if (isFatalStreamStatus(s.status)) {
|
|
128
|
+
this.failFatally(t);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
throw t;
|
|
132
|
+
}
|
|
133
|
+
if (!s.body) throw new LoopstackApiError(s.status, void 0, "Event stream response had no body");
|
|
134
|
+
this.setStatus("open");
|
|
135
|
+
let c = a > 0;
|
|
136
|
+
a = 0, this.resetWatchdog(), c && this.lastEventId === void 0 && this.dispatchMessage({
|
|
137
|
+
type: "stream.reset",
|
|
138
|
+
userId: null,
|
|
139
|
+
workerId: ""
|
|
99
140
|
});
|
|
100
|
-
|
|
101
|
-
this.setStatus("open"), i = 0, this.resetWatchdog();
|
|
102
|
-
let s = createSseParser((e) => {
|
|
141
|
+
let l = createSseParser((e) => {
|
|
103
142
|
this.resetWatchdog(), e.id !== void 0 && e.id !== "" && (this.lastEventId = e.id), e.event !== "ping" && e.data && this.dispatch(e.data);
|
|
104
|
-
}),
|
|
143
|
+
}), u = s.body.getReader(), d = new TextDecoder();
|
|
105
144
|
for (;;) {
|
|
106
|
-
let { done: e, value: t } = await
|
|
145
|
+
let { done: e, value: t } = await u.read();
|
|
107
146
|
if (e) break;
|
|
108
|
-
|
|
147
|
+
l.feed(d.decode(t, { stream: !0 }));
|
|
109
148
|
}
|
|
110
149
|
} catch {}
|
|
111
150
|
if (this.clearWatchdog(), this.currentStatus === "open" && this.setStatus("connecting"), this.closed || this.subscriberCount === 0) break;
|
|
112
|
-
|
|
113
|
-
let
|
|
114
|
-
await new Promise((e) => setTimeout(e,
|
|
151
|
+
a++;
|
|
152
|
+
let s = Math.min(this.config.maxRetryDelayMs ?? 1e4, INITIAL_RETRY_DELAY_MS * 2 ** (a - 1)) * (.8 + Math.random() * .4);
|
|
153
|
+
await new Promise((e) => setTimeout(e, s));
|
|
115
154
|
}
|
|
116
|
-
this.running = !1, this.setStatus(this.closed ? "closed" : "idle");
|
|
155
|
+
this.running = !1, this.setStatus(this.closed || this.fatalError ? "closed" : "idle");
|
|
156
|
+
}
|
|
157
|
+
failFatally(e) {
|
|
158
|
+
this.fatalError = e, this.clearWatchdog();
|
|
159
|
+
for (let t of this.errorHandlers) t(e);
|
|
117
160
|
}
|
|
118
161
|
dispatch(e) {
|
|
119
162
|
let n;
|
|
@@ -124,9 +167,7 @@ var LoopstackStream = class {
|
|
|
124
167
|
}
|
|
125
168
|
let r = ClientMessageSchema.safeParse(n);
|
|
126
169
|
if (r.success) {
|
|
127
|
-
|
|
128
|
-
for (let t of this.handlers.get(e.type) ?? []) t(e);
|
|
129
|
-
for (let t of this.anyHandlers) t(e);
|
|
170
|
+
this.dispatchMessage(r.data);
|
|
130
171
|
return;
|
|
131
172
|
}
|
|
132
173
|
let i = n && typeof n == "object" && "type" in n && typeof n.type == "string" ? n.type : "unknown";
|
|
@@ -135,6 +176,10 @@ var LoopstackStream = class {
|
|
|
135
176
|
raw: n
|
|
136
177
|
});
|
|
137
178
|
}
|
|
179
|
+
dispatchMessage(e) {
|
|
180
|
+
for (let t of this.handlers.get(e.type) ?? []) t(e);
|
|
181
|
+
for (let t of this.anyHandlers) t(e);
|
|
182
|
+
}
|
|
138
183
|
resetWatchdog() {
|
|
139
184
|
this.clearWatchdog(), this.watchdog = setTimeout(() => {
|
|
140
185
|
this.abortController?.abort();
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { WorkflowState } from "../enums/workflow-state.enum.js";
|
|
2
|
+
const DISPLAY_WIDGETS = new Set([
|
|
3
|
+
"message",
|
|
4
|
+
"llm-message",
|
|
5
|
+
"ai-message",
|
|
6
|
+
"markdown",
|
|
7
|
+
"plain",
|
|
8
|
+
"error",
|
|
9
|
+
"link",
|
|
10
|
+
"debug"
|
|
11
|
+
]);
|
|
12
|
+
function declaredTransitions(e) {
|
|
13
|
+
let n = [], r = e.options?.transition;
|
|
14
|
+
typeof r == "string" && n.push(r);
|
|
15
|
+
let i = e.options?.actions;
|
|
16
|
+
if (Array.isArray(i)) for (let e of i) typeof e.transition == "string" && n.push(e.transition);
|
|
17
|
+
return n;
|
|
18
|
+
}
|
|
19
|
+
function resolveSubmitTransition(e, n) {
|
|
20
|
+
let i = declaredTransitions(e);
|
|
21
|
+
return i.length > 0 ? i.find((e) => n.includes(e)) : n.length === 1 ? n[0] : void 0;
|
|
22
|
+
}
|
|
23
|
+
function widgetState(e, n, r, a = !0) {
|
|
24
|
+
return e.showWhen && !e.showWhen.includes(n ?? "") ? "hidden" : e.enabledWhen && !e.enabledWhen.includes(n ?? "") || !a || resolveSubmitTransition(e, r) === void 0 ? "disabled" : "active";
|
|
25
|
+
}
|
|
26
|
+
function isDocumentVisible(e, n, r) {
|
|
27
|
+
return !(n.internal || e.tags?.includes("internal") || n.hideAtPlaces?.includes(r ?? ""));
|
|
28
|
+
}
|
|
29
|
+
function isDocumentActive(e, n, r) {
|
|
30
|
+
return e.place === r || !!n.enableAtPlaces?.includes(r ?? "");
|
|
31
|
+
}
|
|
32
|
+
function isAnswered(e) {
|
|
33
|
+
return e?.answer !== void 0;
|
|
34
|
+
}
|
|
35
|
+
function isAnswerableState(n, r) {
|
|
36
|
+
return r.length === 0 ? !1 : n === WorkflowState.Waiting || n === WorkflowState.Paused || n === WorkflowState.Failed;
|
|
37
|
+
}
|
|
38
|
+
function evaluateWorkflowPrompts(e, l, u, d = []) {
|
|
39
|
+
if (!isAnswerableState(e.status, e.availableTransitions)) return [];
|
|
40
|
+
let f = [], p = e.availableTransitions;
|
|
41
|
+
for (let c of l) {
|
|
42
|
+
let l = u.get(c.documentName);
|
|
43
|
+
l && (DISPLAY_WIDGETS.has(l.widget) || isDocumentVisible(c, l, e.place) && isDocumentActive(c, l, e.place) && (isAnswered(c.content) || f.push({
|
|
44
|
+
kind: "document",
|
|
45
|
+
workflow: e,
|
|
46
|
+
document: c,
|
|
47
|
+
widget: l,
|
|
48
|
+
state: widgetState(l, e.place, p),
|
|
49
|
+
submitTransition: resolveSubmitTransition(l, p),
|
|
50
|
+
submitDeclared: declaredTransitions(l).length > 0
|
|
51
|
+
})));
|
|
52
|
+
}
|
|
53
|
+
for (let n of d) {
|
|
54
|
+
let o = widgetState(n, e.place, p);
|
|
55
|
+
o !== "hidden" && f.push({
|
|
56
|
+
kind: "workflow",
|
|
57
|
+
workflow: e,
|
|
58
|
+
widget: n,
|
|
59
|
+
state: o,
|
|
60
|
+
submitTransition: resolveSubmitTransition(n, p),
|
|
61
|
+
submitDeclared: declaredTransitions(n).length > 0
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return f.push({
|
|
65
|
+
kind: "bare",
|
|
66
|
+
workflow: e,
|
|
67
|
+
state: "active",
|
|
68
|
+
...p.length === 1 && { submitTransition: p[0] }
|
|
69
|
+
}), f;
|
|
70
|
+
}
|
|
71
|
+
function pickPrompt(e, n = () => !0) {
|
|
72
|
+
let r = {};
|
|
73
|
+
for (let i of e) {
|
|
74
|
+
if (i.kind === "bare") {
|
|
75
|
+
r.fallback ??= i;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (i.state === "active") {
|
|
79
|
+
if (n(i)) return r.prompt = i, r;
|
|
80
|
+
i.submitDeclared && (r.blocked ??= i);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return r;
|
|
84
|
+
}
|
|
85
|
+
function toParkView(e) {
|
|
86
|
+
let { workflow: n, document: r, widget: i } = e, a = n.availableTransitions, o, s = i?.options?.actions;
|
|
87
|
+
return Array.isArray(s) && (o = s.filter((e) => typeof e.transition != "string" || a.includes(e.transition)).map((e) => typeof e.label == "string" ? e.label : String(e.transition ?? "")).filter((e) => e.length > 0)), {
|
|
88
|
+
workflowId: n.id,
|
|
89
|
+
workflowName: n.workflowName,
|
|
90
|
+
place: n.place,
|
|
91
|
+
status: n.status,
|
|
92
|
+
...i && { widget: i.widget },
|
|
93
|
+
...r && { documentName: r.documentName },
|
|
94
|
+
...r?.content && { content: r.content },
|
|
95
|
+
...i?.schema && { schema: i.schema },
|
|
96
|
+
...i?.options && { options: i.options },
|
|
97
|
+
transitions: a,
|
|
98
|
+
...e.submitTransition && { defaultTransition: e.submitTransition },
|
|
99
|
+
...o?.length && { actions: o }
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export { DISPLAY_WIDGETS, declaredTransitions, evaluateWorkflowPrompts, isAnswerableState, isAnswered, isDocumentActive, isDocumentVisible, pickPrompt, resolveSubmitTransition, toParkView, widgetState };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
z.object({
|
|
3
|
+
workflowId: z.string(),
|
|
4
|
+
workflowName: z.string(),
|
|
5
|
+
place: z.string().nullable(),
|
|
6
|
+
status: z.string(),
|
|
7
|
+
widget: z.string().optional(),
|
|
8
|
+
documentName: z.string().optional(),
|
|
9
|
+
content: z.record(z.string(), z.unknown()).optional(),
|
|
10
|
+
schema: z.record(z.string(), z.unknown()).optional(),
|
|
11
|
+
options: z.record(z.string(), z.unknown()).optional(),
|
|
12
|
+
transitions: z.array(z.string()),
|
|
13
|
+
defaultTransition: z.string().optional(),
|
|
14
|
+
actions: z.array(z.string()).optional()
|
|
15
|
+
});
|
|
@@ -9,10 +9,10 @@ import ErrorSnackbar_default from "../components/feedback/ErrorSnackbar.js";
|
|
|
9
9
|
import { ReactFlowProvider } from "../node_modules/@xyflow/react/dist/esm/index.js";
|
|
10
10
|
import WorkflowFlowViewer_default from "../features/debug/components/WorkflowFlowViewer.js";
|
|
11
11
|
import "../features/debug/index.js";
|
|
12
|
+
import config_default from "../config.js";
|
|
12
13
|
import WorkflowItem_default from "../features/workbench/WorkflowItem.js";
|
|
13
14
|
import WorkflowHistoryList_default from "../features/workbench/components/WorkflowHistoryList.js";
|
|
14
15
|
import { NewRunDialog } from "../features/workbench/components/NewRunDialog.js";
|
|
15
|
-
import config_default from "../config.js";
|
|
16
16
|
import "../features/workbench/index.js";
|
|
17
17
|
import { c } from "react/compiler-runtime";
|
|
18
18
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
@@ -46,27 +46,27 @@ function PreviewWorkbenchPage() {
|
|
|
46
46
|
}), e[3] = t, e[4] = o), o;
|
|
47
47
|
}
|
|
48
48
|
function PreviewWorkbenchContent(n) {
|
|
49
|
-
let i = c(49), { workflowId:
|
|
50
|
-
i[0] !== w.data || i[1] !==
|
|
49
|
+
let i = c(49), { workflowId: d, onNewRunSuccess: h } = n, _ = useRef(null), [y, b] = useState("output"), [x, S] = useState(!1), w = useWorkflow(d), T = useRef(!1), O = useWorkflowConfigByName(w.data?.workflowName), A, j;
|
|
50
|
+
i[0] !== w.data || i[1] !== d ? (A = () => {
|
|
51
51
|
!w.data || T.current || w.data.status === WorkflowState.Completed && window.parent !== window && (T.current = !0, window.parent.postMessage({
|
|
52
52
|
type: EMBED_MESSAGE_TYPE,
|
|
53
|
-
workflowId:
|
|
53
|
+
workflowId: d
|
|
54
54
|
}, window.location.origin));
|
|
55
|
-
}, j = [w.data,
|
|
55
|
+
}, j = [w.data, d], i[0] = w.data, i[1] = d, i[2] = A, i[3] = j) : (A = i[2], j = i[3]), useEffect(A, j);
|
|
56
56
|
let M, N;
|
|
57
|
-
i[4] ===
|
|
57
|
+
i[4] === d ? (M = i[5], N = i[6]) : (M = () => {
|
|
58
58
|
if (window.parent === window || !_.current) return;
|
|
59
59
|
let e = new ResizeObserver(() => {
|
|
60
60
|
if (!_.current) return;
|
|
61
61
|
let e = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
|
|
62
62
|
window.parent.postMessage({
|
|
63
63
|
type: EMBED_RESIZE_MESSAGE_TYPE,
|
|
64
|
-
workflowId:
|
|
64
|
+
workflowId: d,
|
|
65
65
|
height: e
|
|
66
66
|
}, window.location.origin);
|
|
67
67
|
});
|
|
68
68
|
return e.observe(_.current), () => e.disconnect();
|
|
69
|
-
}, N = [
|
|
69
|
+
}, N = [d], i[4] = d, i[5] = M, i[6] = N), useEffect(M, N);
|
|
70
70
|
let P;
|
|
71
71
|
i[7] === h ? P = i[8] : (P = (e) => {
|
|
72
72
|
S(!1), h(e);
|
|
@@ -143,12 +143,12 @@ function PreviewWorkbenchContent(n) {
|
|
|
143
143
|
})
|
|
144
144
|
}), i[21] = y, i[22] = w.data, i[23] = w.isLoading, i[24] = q) : q = i[24];
|
|
145
145
|
let J;
|
|
146
|
-
i[25] !== y || i[26] !== w.data || i[27] !== w.isLoading || i[28] !== O || i[29] !==
|
|
146
|
+
i[25] !== y || i[26] !== w.data || i[27] !== w.isLoading || i[28] !== O || i[29] !== d ? (J = y === "graph" && /* @__PURE__ */ jsx("div", {
|
|
147
147
|
className: "h-full",
|
|
148
148
|
children: /* @__PURE__ */ jsx(LoadingCentered_default, {
|
|
149
149
|
loading: w.isLoading,
|
|
150
150
|
children: w.data ? /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(WorkflowFlowViewer_default, {
|
|
151
|
-
workflowId:
|
|
151
|
+
workflowId: d,
|
|
152
152
|
workflows: [w.data],
|
|
153
153
|
workflowConfig: O.data,
|
|
154
154
|
direction: "TB"
|
|
@@ -160,7 +160,7 @@ function PreviewWorkbenchContent(n) {
|
|
|
160
160
|
})
|
|
161
161
|
})
|
|
162
162
|
})
|
|
163
|
-
}), i[25] = y, i[26] = w.data, i[27] = w.isLoading, i[28] = O, i[29] =
|
|
163
|
+
}), i[25] = y, i[26] = w.data, i[27] = w.isLoading, i[28] = O, i[29] = d, i[30] = J) : J = i[30];
|
|
164
164
|
let Y;
|
|
165
165
|
i[31] !== y || i[32] !== w.data ? (Y = y === "run-log" && /* @__PURE__ */ jsx("div", {
|
|
166
166
|
className: "px-4",
|
|
@@ -206,9 +206,9 @@ var STATUS_DOT_COLORS = {
|
|
|
206
206
|
pending: "bg-muted-foreground"
|
|
207
207
|
};
|
|
208
208
|
function PreviewEmptyState(e) {
|
|
209
|
-
let t = c(24), { newRunDialogOpen: r, onNewRunDialogOpenChange: o, onNewRunSuccess: s } = e, l = useNavigate(), { router: u } = useStudio(), [d, f] = useState(3),
|
|
210
|
-
t[0] === Symbol.for("react.memo_cache_sentinel") ? (
|
|
211
|
-
let h = useFilterWorkflows(void 0,
|
|
209
|
+
let t = c(24), { newRunDialogOpen: r, onNewRunDialogOpenChange: o, onNewRunSuccess: s } = e, l = useNavigate(), { router: u } = useStudio(), [d, f] = useState(3), p;
|
|
210
|
+
t[0] === Symbol.for("react.memo_cache_sentinel") ? (p = { parentId: null }, t[0] = p) : p = t[0];
|
|
211
|
+
let h = useFilterWorkflows(void 0, p, "createdAt", "DESC", 0, d), g;
|
|
212
212
|
t[1] === h.data?.data ? g = t[2] : (g = h.data?.data ?? [], t[1] = h.data?.data, t[2] = g);
|
|
213
213
|
let _ = g, se = h.data?.total ?? 0, y = _.length < se, x;
|
|
214
214
|
t[3] === o ? x = t[4] : (x = () => o(!0), t[3] = o, t[4] = x);
|
|
@@ -358,19 +358,19 @@ function EmbedLogsContent() {
|
|
|
358
358
|
className: "text-xs font-medium text-muted-foreground",
|
|
359
359
|
children: "Application Logs"
|
|
360
360
|
}), e[6] = u) : u = e[6];
|
|
361
|
-
let
|
|
362
|
-
e[7] === i ?
|
|
363
|
-
let
|
|
364
|
-
e[9] === Symbol.for("react.memo_cache_sentinel") ? (
|
|
361
|
+
let f;
|
|
362
|
+
e[7] === i ? f = e[8] : (f = () => void i.refetch(), e[7] = i, e[8] = f);
|
|
363
|
+
let p = `text-muted-foreground hover:text-foreground rounded-md p-1 transition-colors hover:cursor-pointer ${i.isFetching ? "animate-spin" : ""}`, m;
|
|
364
|
+
e[9] === Symbol.for("react.memo_cache_sentinel") ? (m = /* @__PURE__ */ jsx(RefreshCw, { className: "h-3 w-3" }), e[9] = m) : m = e[9];
|
|
365
365
|
let h;
|
|
366
|
-
e[10] !==
|
|
366
|
+
e[10] !== f || e[11] !== p ? (h = /* @__PURE__ */ jsxs("div", {
|
|
367
367
|
className: "flex h-9 shrink-0 items-center justify-between border-b bg-muted/30 px-3",
|
|
368
368
|
children: [u, /* @__PURE__ */ jsx("button", {
|
|
369
|
-
onClick:
|
|
370
|
-
className:
|
|
371
|
-
children:
|
|
369
|
+
onClick: f,
|
|
370
|
+
className: p,
|
|
371
|
+
children: m
|
|
372
372
|
})]
|
|
373
|
-
}), e[10] =
|
|
373
|
+
}), e[10] = f, e[11] = p, e[12] = h) : h = e[12];
|
|
374
374
|
let _;
|
|
375
375
|
e[13] !== l || e[14] !== i.data || e[15] !== i.error || e[16] !== i.isLoading ? (_ = /* @__PURE__ */ jsx("div", {
|
|
376
376
|
className: "flex-1 overflow-auto bg-background",
|
|
@@ -4,7 +4,8 @@ import { jsx } from "react/jsx-runtime";
|
|
|
4
4
|
var STORAGE_KEY = "loopstack:studio-preferences", DEFAULTS = {
|
|
5
5
|
leftSidebarOpen: !1,
|
|
6
6
|
activePanel: null,
|
|
7
|
-
panelSizes: {}
|
|
7
|
+
panelSizes: {},
|
|
8
|
+
workbenchView: "classic"
|
|
8
9
|
}, StudioPreferencesContext = createContext(null);
|
|
9
10
|
function readFromStorage() {
|
|
10
11
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loopstack/loopstack-studio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.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.
|
|
30
|
-
"@loopstack/contracts": "^0.
|
|
31
|
-
"@loopstack/react": "^
|
|
29
|
+
"@loopstack/client": "^0.38.0",
|
|
30
|
+
"@loopstack/contracts": "^0.38.0",
|
|
31
|
+
"@loopstack/react": "^2.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",
|