wizards 0.1.11 → 0.2.1
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/README.md +3 -0
- package/apps/runtime/dist/agents/architect.js +6 -4
- package/apps/runtime/dist/app.js +38 -4
- package/apps/runtime/dist/auth/local-ticket.js +8 -5
- package/apps/runtime/dist/authoring/guide.js +10 -2
- package/apps/runtime/dist/cli/connect.js +531 -0
- package/apps/runtime/dist/cli/environment.js +8 -1
- package/apps/runtime/dist/cli/home.js +1 -0
- package/apps/runtime/dist/cli/main.js +17 -0
- package/apps/runtime/dist/cli/mcp.js +175 -0
- package/apps/runtime/dist/cli/setup.js +49 -0
- package/apps/runtime/dist/db/client.js +13 -0
- package/apps/runtime/dist/engine/runner.js +3 -0
- package/apps/runtime/dist/env.js +18 -4
- package/apps/runtime/dist/index.js +3 -0
- package/apps/runtime/dist/mcp/auth.js +26 -0
- package/apps/runtime/dist/mcp/flow-app.js +94 -0
- package/apps/runtime/dist/mcp/handler.js +15 -5
- package/apps/runtime/dist/mcp/seen.js +65 -0
- package/apps/runtime/dist/mcp/tools.js +158 -5
- package/apps/runtime/dist/plugins/discovery.js +144 -0
- package/apps/runtime/dist/plugins/events.js +40 -0
- package/apps/runtime/dist/plugins/loader.js +277 -0
- package/apps/runtime/dist/plugins/migrations.js +69 -0
- package/apps/runtime/dist/plugins/registry.js +105 -0
- package/apps/runtime/dist/routes/plugins.js +160 -0
- package/apps/runtime/dist/routes/runs.js +7 -3
- package/apps/runtime/dist/routes/studio.js +20 -0
- package/apps/runtime/dist/secrets/signing.js +21 -3
- package/apps/runtime/dist/services/runs.js +190 -28
- package/apps/runtime/dist/services/wizards.js +30 -4
- package/apps/runtime/dist/tools/index.js +2 -0
- package/apps/runtime/dist/tools/plugin.js +43 -0
- package/apps/web/dist/assets/ChangelogDialog-Co_9fs61.js +1 -0
- package/apps/web/dist/assets/ChatPanel-Br3nYkUc.js +1 -0
- package/apps/web/dist/assets/CreditsDialog-D3fZRqXH.js +1 -0
- package/apps/web/dist/assets/EditorPage-BSjQC6FE.js +2 -0
- package/apps/web/dist/assets/FlowPreview-CjUK5046.js +1 -0
- package/apps/web/dist/assets/HomePage-8v4HqIbP.js +1 -0
- package/apps/web/dist/assets/ImportWizard-DiV62Uno.js +1 -0
- package/apps/web/dist/assets/{LocalRuntime-DKqEzptp.js → LocalRuntime-CTyLGC98.js} +2 -2
- package/apps/web/dist/assets/NewWizardPage-BBL2yenw.js +2 -0
- package/apps/web/dist/assets/PublicRunner-BwtoEVlE.js +1 -0
- package/apps/web/dist/assets/RunnerView-DOizlTad.js +2 -0
- package/apps/web/dist/assets/SettingsPage-CBDv04YS.js +2 -0
- package/apps/web/dist/assets/SetupPage-CfXTOaIm.js +1 -0
- package/apps/web/dist/assets/SharePage-CgByqrAF.js +1 -0
- package/apps/web/dist/assets/api-KMi35npD.js +10 -0
- package/apps/web/dist/assets/{arrow-left-UpjOBfQp.js → arrow-left-hTN1VoH1.js} +1 -1
- package/apps/web/dist/assets/{arrow-right-CucQycEy.js → arrow-right-6FyN3e7D.js} +1 -1
- package/apps/web/dist/assets/changelog-03JgixQA.js +1 -0
- package/apps/web/dist/assets/check-CUpby_J9.js +1 -0
- package/apps/web/dist/assets/{createLucideIcon-DBu2Ovxj.js → createLucideIcon-q3MZMmnf.js} +1 -1
- package/apps/web/dist/assets/definition-DndaH5Ow.js +55 -0
- package/apps/web/dist/assets/engenty-Cm8yZLON.js +1 -0
- package/apps/web/dist/assets/esm-rJY59Ixx.js +7 -0
- package/apps/web/dist/assets/{external-link-CRg6DVdO.js → external-link-MAL7vJYj.js} +1 -1
- package/apps/web/dist/assets/{fluffy-engenty-CJ3wCQgT.js → fluffy-engenty-D7rFrNcJ.js} +2 -2
- package/apps/web/dist/assets/index-B9YVjvVY.css +1 -0
- package/apps/web/dist/assets/index-BmpnE7IO.js +10 -0
- package/apps/web/dist/assets/jsx-runtime-D3jfb0Ew.js +1 -0
- package/apps/web/dist/assets/meta-4R1Lnr25.js +1 -0
- package/apps/web/dist/assets/{mic-CeqQ89Dj.js → mic-Bvz4mA2j.js} +1 -1
- package/apps/web/dist/assets/oss-credits-roB62QJu.js +1 -0
- package/apps/web/dist/assets/{outputs-CHe6KRLc.js → outputs-COE_nvAw.js} +2 -2
- package/apps/web/dist/assets/plug-CLjyCoHB.js +1 -0
- package/apps/web/dist/assets/{plus-HA210wXA.js → plus-Du-Jx8aI.js} +1 -1
- package/apps/web/dist/assets/react-dom-DenslgJm.js +1 -0
- package/apps/web/dist/assets/session-B6-6VomQ.js +1 -0
- package/apps/web/dist/assets/type-Bj9H3eOK.js +1 -0
- package/apps/web/dist/assets/ui-Cs6lpsmj.js +1 -0
- package/apps/web/dist/assets/{upload-DsgLfQ3U.js → upload--J5bZhEM.js} +1 -1
- package/apps/web/dist/assets/{video-Dk1fuTDl.js → video-CjgmvRDk.js} +1 -1
- package/apps/web/dist/assets/{wand-sparkles-Bf97fs8T.js → wand-sparkles-CKxArWPY.js} +1 -1
- package/apps/web/dist/index.html +10 -7
- package/apps/web/dist/mcp/flow.html +748 -0
- package/modules/README.md +15 -0
- package/node_modules/@engenty-wizards/plugin-sdk/dist/index.d.ts +144 -0
- package/node_modules/@engenty-wizards/plugin-sdk/dist/index.js +4 -0
- package/node_modules/@engenty-wizards/plugin-sdk/dist/studio.d.ts +80 -0
- package/node_modules/@engenty-wizards/plugin-sdk/dist/studio.js +4 -0
- package/node_modules/@engenty-wizards/plugin-sdk/package.json +10 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +18 -6
- package/node_modules/@engenty-wizards/shared/dist/definition.js +22 -1
- package/package.json +6 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/skills/use-wizard/SKILL.md +18 -0
- package/apps/web/dist/assets/ChangelogDialog-DURK75KD.js +0 -1
- package/apps/web/dist/assets/ChatPanel-DZhZJZCP.js +0 -1
- package/apps/web/dist/assets/CreditsDialog-CLUOVBLG.js +0 -1
- package/apps/web/dist/assets/EditorPage-PGCEQdiC.js +0 -2
- package/apps/web/dist/assets/FlowPreview-CqJUNW13.js +0 -1
- package/apps/web/dist/assets/HomePage-CRkDMNM2.js +0 -1
- package/apps/web/dist/assets/ImportWizard-DX1YtFPv.js +0 -1
- package/apps/web/dist/assets/NewWizardPage-BPJrYi2m.js +0 -2
- package/apps/web/dist/assets/PublicRunner-B3T244Ry.js +0 -1
- package/apps/web/dist/assets/RunnerView-DgYaOHIH.js +0 -2
- package/apps/web/dist/assets/SettingsPage-LBVqEwXs.js +0 -2
- package/apps/web/dist/assets/SetupPage-DAyJs-hK.js +0 -1
- package/apps/web/dist/assets/SharePage-oKGavxJt.js +0 -1
- package/apps/web/dist/assets/api-DbPn6Dge.js +0 -10
- package/apps/web/dist/assets/changelog-BJkYErYt.js +0 -1
- package/apps/web/dist/assets/check-Bjx41xbB.js +0 -1
- package/apps/web/dist/assets/definition-cy7uvY5L.js +0 -55
- package/apps/web/dist/assets/engenty-CWIFpgKq.js +0 -1
- package/apps/web/dist/assets/esm-ZHEGGS6s.js +0 -7
- package/apps/web/dist/assets/index-BRy5sz4a.js +0 -10
- package/apps/web/dist/assets/index-CQ_q9iMO.css +0 -1
- package/apps/web/dist/assets/jsx-runtime-Dk72oS4N.js +0 -1
- package/apps/web/dist/assets/meta-2YMHa2hT.js +0 -1
- package/apps/web/dist/assets/oss-credits-cPuZUFHD.js +0 -1
- package/apps/web/dist/assets/type-BzYgVWKL.js +0 -1
- package/apps/web/dist/assets/ui-tO4ZXbfh.js +0 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { formatsFor } from "@engenty-wizards/shared/definition";
|
|
2
|
-
import { and, count, desc, eq, inArray } from "drizzle-orm";
|
|
2
|
+
import { and, count, desc, eq, inArray, or } from "drizzle-orm";
|
|
3
3
|
import { canSpend, MICROS_PER_CREDIT } from "../credits/credits.js";
|
|
4
4
|
import { db, schema } from "../db/client.js";
|
|
5
|
-
import { unattended } from "../engine/asks.js";
|
|
5
|
+
import { answerAsk, unattended } from "../engine/asks.js";
|
|
6
6
|
import { emitEvent, recentEvents, subscribe } from "../engine/events.js";
|
|
7
|
-
import { createRun, RunInputError, reviewStep, submitPage } from "../engine/runner.js";
|
|
7
|
+
import { cancel, createRun, goBack, NoCreditsError, RunConflict, RunInputError, retry, reviewStep, submitPage, } from "../engine/runner.js";
|
|
8
8
|
import { ModelUnavailableError } from "../model-errors.js";
|
|
9
9
|
import { signedUrl } from "../secrets/signing.js";
|
|
10
10
|
import { currentTenant } from "../tenants/tenant.js";
|
|
11
11
|
import { notFound, ServiceError } from "./errors.js";
|
|
12
|
-
import { ownedWizard, requireClean, studioUrl } from "./wizards.js";
|
|
12
|
+
import { ownedWizard, requireClean, shareUrl, studioUrl } from "./wizards.js";
|
|
13
13
|
/** Test runs an MCP client started with answers: pages are filled and reviews accepted for it. */
|
|
14
14
|
const autopilots = new Set();
|
|
15
15
|
export async function startTestRun(userId, wizardId, autopilot) {
|
|
@@ -95,9 +95,15 @@ function fly(runId, answers, acceptReviews) {
|
|
|
95
95
|
const timeout = setTimeout(land, 30 * 60_000);
|
|
96
96
|
void step();
|
|
97
97
|
}
|
|
98
|
-
|
|
98
|
+
/**
|
|
99
|
+
* A run the caller may see: any test run of their tenant, or a run they started themselves
|
|
100
|
+
* from an MCP client (run_wizard). `test` narrows it to test runs.
|
|
101
|
+
*/
|
|
102
|
+
async function ownedRun(userId, runId, only) {
|
|
99
103
|
const run = await db.query.run.findFirst({
|
|
100
|
-
where: and(eq(schema.run.id, runId), eq(schema.run.tenantId, currentTenant()),
|
|
104
|
+
where: and(eq(schema.run.id, runId), eq(schema.run.tenantId, currentTenant()), only === "test"
|
|
105
|
+
? eq(schema.run.mode, "test")
|
|
106
|
+
: or(eq(schema.run.mode, "test"), eq(schema.run.userId, userId))),
|
|
101
107
|
});
|
|
102
108
|
if (!run) {
|
|
103
109
|
throw notFound();
|
|
@@ -108,9 +114,9 @@ async function ownedTestRun(_userId, runId) {
|
|
|
108
114
|
function moving(run) {
|
|
109
115
|
return run.status === "running" || (run.status === "waiting_input" && autopilots.has(run.id));
|
|
110
116
|
}
|
|
111
|
-
async function waitWhileMoving(userId, runId, seconds) {
|
|
117
|
+
async function waitWhileMoving(userId, runId, seconds, only) {
|
|
112
118
|
const deadline = Date.now() + seconds * 1000;
|
|
113
|
-
let run = await
|
|
119
|
+
let run = await ownedRun(userId, runId, only);
|
|
114
120
|
while (moving(run) && Date.now() < deadline) {
|
|
115
121
|
await new Promise((resolve) => {
|
|
116
122
|
const unsubscribe = subscribe(runId, () => {
|
|
@@ -123,7 +129,7 @@ async function waitWhileMoving(userId, runId, seconds) {
|
|
|
123
129
|
resolve();
|
|
124
130
|
}, deadline - Date.now());
|
|
125
131
|
});
|
|
126
|
-
run = await
|
|
132
|
+
run = await ownedRun(userId, runId, only);
|
|
127
133
|
}
|
|
128
134
|
return run;
|
|
129
135
|
}
|
|
@@ -139,9 +145,88 @@ function deliverableFormats(run, step) {
|
|
|
139
145
|
.find((d) => d.from === step.id);
|
|
140
146
|
return listed ? listed.formats.filter((f) => possible.includes(f)) : [];
|
|
141
147
|
}
|
|
142
|
-
/**
|
|
143
|
-
|
|
144
|
-
|
|
148
|
+
/** Field kinds an MCP client can answer with plain values; the others need the run page. */
|
|
149
|
+
const CHAT_KINDS = new Set([
|
|
150
|
+
"text",
|
|
151
|
+
"textarea",
|
|
152
|
+
"number",
|
|
153
|
+
"select",
|
|
154
|
+
"multiselect",
|
|
155
|
+
"date",
|
|
156
|
+
"email",
|
|
157
|
+
"url",
|
|
158
|
+
"toggle",
|
|
159
|
+
"color",
|
|
160
|
+
"items",
|
|
161
|
+
"location",
|
|
162
|
+
]);
|
|
163
|
+
/** Where the person can go on in a browser: the run page of a live run, the studio for a test. */
|
|
164
|
+
/** The live run's page — the wizard itself, never the studio. A test run has none. */
|
|
165
|
+
async function browserUrl(run) {
|
|
166
|
+
if (run.mode === "test") {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
const w = await db.query.wizard.findFirst({ where: eq(schema.wizard.id, run.wizardId) });
|
|
170
|
+
return w ? `${shareUrl(w.shareToken)}/${run.id}` : null;
|
|
171
|
+
}
|
|
172
|
+
function waitingFor(run, current) {
|
|
173
|
+
if (run.status === "running" && run.ask) {
|
|
174
|
+
const ask = run.ask;
|
|
175
|
+
return ask.kind === "confirm"
|
|
176
|
+
? {
|
|
177
|
+
ask: ask.id,
|
|
178
|
+
kind: ask.kind,
|
|
179
|
+
reason: ask.reason,
|
|
180
|
+
service: ask.service,
|
|
181
|
+
action: ask.action.summary,
|
|
182
|
+
input: clip(ask.input, 1500),
|
|
183
|
+
hint: "Ask the person, then answer_ask with allow or skip.",
|
|
184
|
+
}
|
|
185
|
+
: {
|
|
186
|
+
ask: ask.id,
|
|
187
|
+
kind: ask.kind,
|
|
188
|
+
reason: ask.reason,
|
|
189
|
+
site: ask.site.host,
|
|
190
|
+
hint: "A sign-in: the person types it on the run page (browserUrl).",
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
if (run.status !== "waiting_input" || !current) {
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
if (current.type === "page") {
|
|
197
|
+
return {
|
|
198
|
+
page: current.id,
|
|
199
|
+
title: current.title,
|
|
200
|
+
fields: current.fields.map((f) => ({
|
|
201
|
+
id: f.id,
|
|
202
|
+
label: f.label,
|
|
203
|
+
kind: f.kind,
|
|
204
|
+
required: Boolean(f.required),
|
|
205
|
+
options: f.options,
|
|
206
|
+
placeholder: f.placeholder,
|
|
207
|
+
help: f.help,
|
|
208
|
+
default: f.default,
|
|
209
|
+
value: run.state.values[f.id],
|
|
210
|
+
columns: f.columns,
|
|
211
|
+
// A file, a recording or a signature comes from the person's device: the run page.
|
|
212
|
+
inChat: CHAT_KINDS.has(f.kind),
|
|
213
|
+
})),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
if (current.type === "review") {
|
|
217
|
+
return {
|
|
218
|
+
review: current.id,
|
|
219
|
+
title: current.title,
|
|
220
|
+
show: current.show,
|
|
221
|
+
editable: Boolean(current.edit),
|
|
222
|
+
hint: "Show the person the outputs, then review_step: accept, or regenerate one with a note.",
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
/** What a run did so far, for a client without the run page: outputs, links, cost, errors. */
|
|
228
|
+
export async function runReport(userId, runId, waitSeconds = 0, only) {
|
|
229
|
+
const run = await waitWhileMoving(userId, runId, waitSeconds, only);
|
|
145
230
|
const current = run.definition.steps.find((s) => s.id === run.cursor) ?? null;
|
|
146
231
|
const base = `/api/runs/${run.id}`;
|
|
147
232
|
const outputs = run.definition.steps.flatMap((step) => {
|
|
@@ -167,25 +252,19 @@ export async function testRunReport(userId, runId, waitSeconds = 0) {
|
|
|
167
252
|
},
|
|
168
253
|
];
|
|
169
254
|
});
|
|
170
|
-
const waitingFor = run.status === "waiting_input" && current?.type === "page"
|
|
171
|
-
? {
|
|
172
|
-
page: current.id,
|
|
173
|
-
fields: current.fields.map((f) => ({
|
|
174
|
-
id: f.id,
|
|
175
|
-
label: f.label,
|
|
176
|
-
kind: f.kind,
|
|
177
|
-
required: Boolean(f.required),
|
|
178
|
-
options: f.options,
|
|
179
|
-
})),
|
|
180
|
-
}
|
|
181
|
-
: run.status === "waiting_input" && current?.type === "review"
|
|
182
|
-
? { review: current.id, hint: "Accept or regenerate in the studio." }
|
|
183
|
-
: undefined;
|
|
184
255
|
return {
|
|
185
256
|
runId: run.id,
|
|
257
|
+
wizardId: run.wizardId,
|
|
258
|
+
mode: run.mode,
|
|
186
259
|
status: moving(run) ? "running" : run.status,
|
|
187
260
|
step: current ? { id: current.id, type: current.type, title: current.title } : null,
|
|
188
|
-
|
|
261
|
+
/** Steps behind the run: answered pages and reviews, every step with a result, the end. */
|
|
262
|
+
passed: run.definition.steps
|
|
263
|
+
.filter((s) => run.state.history.includes(s.id) ||
|
|
264
|
+
run.state.outputs[s.id] ||
|
|
265
|
+
(run.status === "done" && s.id === run.cursor))
|
|
266
|
+
.map((s) => s.id),
|
|
267
|
+
waitingFor: waitingFor(run, current),
|
|
189
268
|
error: run.error,
|
|
190
269
|
credits: Math.ceil(run.costMicros / MICROS_PER_CREDIT),
|
|
191
270
|
events: (await recentEvents(run.id, 0, 15)).map((e) => ({
|
|
@@ -194,9 +273,92 @@ export async function testRunReport(userId, runId, waitSeconds = 0) {
|
|
|
194
273
|
message: e.message,
|
|
195
274
|
})),
|
|
196
275
|
outputs,
|
|
197
|
-
|
|
276
|
+
browserUrl: await browserUrl(run),
|
|
277
|
+
...(run.mode === "test" ? { studioUrl: studioUrl(run.wizardId) } : {}),
|
|
198
278
|
};
|
|
199
279
|
}
|
|
280
|
+
export const testRunReport = (userId, runId, waitSeconds = 0) => runReport(userId, runId, waitSeconds, "test");
|
|
281
|
+
/** A command the run refused, as a tool error the client can act on. */
|
|
282
|
+
function refusedInput(err) {
|
|
283
|
+
if (err instanceof RunInputError) {
|
|
284
|
+
throw new ServiceError("invalid", err.message, { fields: err.errors });
|
|
285
|
+
}
|
|
286
|
+
if (err instanceof RunConflict) {
|
|
287
|
+
throw new ServiceError("refused", err.message);
|
|
288
|
+
}
|
|
289
|
+
throw err;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Runs the published version of a wizard for the admin, from their own AI client: a live run
|
|
293
|
+
* that is theirs — no visitor, no share link needed. With answers the first page is filled.
|
|
294
|
+
*/
|
|
295
|
+
export async function startRun(userId, wizardId, answers = {}) {
|
|
296
|
+
const w = await ownedWizard(userId, wizardId);
|
|
297
|
+
if (w.publishedVersion === null) {
|
|
298
|
+
throw new ServiceError("refused", "This wizard is not published yet. Publish it, or try the draft with start_test_run.");
|
|
299
|
+
}
|
|
300
|
+
const version = await db.query.wizardVersion.findFirst({
|
|
301
|
+
where: and(eq(schema.wizardVersion.wizardId, w.id), eq(schema.wizardVersion.version, w.publishedVersion)),
|
|
302
|
+
});
|
|
303
|
+
if (!version) {
|
|
304
|
+
throw notFound();
|
|
305
|
+
}
|
|
306
|
+
if (!(await canSpend())) {
|
|
307
|
+
throw new ServiceError("no_credits", "Dein Guthaben ist aufgebraucht.");
|
|
308
|
+
}
|
|
309
|
+
const runId = await createRun({
|
|
310
|
+
wizardId: w.id,
|
|
311
|
+
definition: version.definition,
|
|
312
|
+
files: version.files,
|
|
313
|
+
version: w.publishedVersion,
|
|
314
|
+
mode: "live",
|
|
315
|
+
userId,
|
|
316
|
+
}).catch((err) => {
|
|
317
|
+
if (err instanceof ModelUnavailableError) {
|
|
318
|
+
throw new ServiceError("refused", err.message);
|
|
319
|
+
}
|
|
320
|
+
if (err instanceof NoCreditsError) {
|
|
321
|
+
throw new ServiceError("no_credits", "Dein Guthaben ist aufgebraucht.");
|
|
322
|
+
}
|
|
323
|
+
throw err;
|
|
324
|
+
});
|
|
325
|
+
const first = version.definition.steps[0];
|
|
326
|
+
if (first?.type !== "page" || !Object.keys(answers).length) {
|
|
327
|
+
return { runId, refused: null };
|
|
328
|
+
}
|
|
329
|
+
const values = Object.fromEntries(first.fields.filter((f) => f.id in answers).map((f) => [f.id, answers[f.id]]));
|
|
330
|
+
// The run is there either way; what did not fit is answered again with answer_page.
|
|
331
|
+
try {
|
|
332
|
+
await submitPage(runId, first.id, values);
|
|
333
|
+
return { runId, refused: null };
|
|
334
|
+
}
|
|
335
|
+
catch (err) {
|
|
336
|
+
if (err instanceof RunInputError) {
|
|
337
|
+
return { runId, refused: err.errors };
|
|
338
|
+
}
|
|
339
|
+
throw err;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
export async function answerRunPage(userId, runId, stepId, values) {
|
|
343
|
+
await ownedRun(userId, runId);
|
|
344
|
+
await submitPage(runId, stepId, values).catch(refusedInput);
|
|
345
|
+
}
|
|
346
|
+
export async function reviewRun(userId, runId, stepId, action) {
|
|
347
|
+
await ownedRun(userId, runId);
|
|
348
|
+
await reviewStep(runId, stepId, action).catch(refusedInput);
|
|
349
|
+
}
|
|
350
|
+
export async function controlRun(userId, runId, action) {
|
|
351
|
+
await ownedRun(userId, runId);
|
|
352
|
+
const command = { back: goBack, retry, cancel }[action];
|
|
353
|
+
await command(runId).catch(refusedInput);
|
|
354
|
+
}
|
|
355
|
+
/** Answers what a running step asks: allow a change in a connected account, or skip it. */
|
|
356
|
+
export async function answerRunAsk(userId, runId, askId, answer) {
|
|
357
|
+
await ownedRun(userId, runId);
|
|
358
|
+
if (!answerAsk(runId, askId, answer === "allow" ? { type: "done" } : { type: "skip" })) {
|
|
359
|
+
throw new ServiceError("refused", "This question is no longer open.");
|
|
360
|
+
}
|
|
361
|
+
}
|
|
200
362
|
export async function listRuns(userId, wizardId) {
|
|
201
363
|
const w = await ownedWizard(userId, wizardId);
|
|
202
364
|
const rows = await db.query.run.findMany({
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { validateWizard, wizardSchema, } from "@engenty-wizards/shared/definition";
|
|
1
|
+
import { pluginToolOf, validateWizard, wizardSchema, } from "@engenty-wizards/shared/definition";
|
|
2
2
|
import { and, desc, eq, sql } from "drizzle-orm";
|
|
3
3
|
import { nanoid } from "nanoid";
|
|
4
4
|
import { applyOps, OpError } from "../authoring/ops.js";
|
|
5
5
|
import { listConnectors } from "../connectors/external.js";
|
|
6
6
|
import { db, schema } from "../db/client.js";
|
|
7
7
|
import { env } from "../env.js";
|
|
8
|
+
import { pluginToolsOf } from "../plugins/registry.js";
|
|
8
9
|
import { dropLinks, putLink } from "../tenants/control.js";
|
|
9
10
|
import { currentTenant } from "../tenants/tenant.js";
|
|
10
11
|
import { changedSteps, emitDraftChanged } from "./draft-events.js";
|
|
@@ -64,7 +65,7 @@ export async function listWizards(_userId, projectId) {
|
|
|
64
65
|
});
|
|
65
66
|
return rows.map(wizardSummary);
|
|
66
67
|
}
|
|
67
|
-
async function publishedVersion(w) {
|
|
68
|
+
export async function publishedVersion(w) {
|
|
68
69
|
if (w.publishedVersion === null) {
|
|
69
70
|
return null;
|
|
70
71
|
}
|
|
@@ -98,9 +99,34 @@ async function connectorIssues(projectId, draft) {
|
|
|
98
99
|
}
|
|
99
100
|
return issues;
|
|
100
101
|
}
|
|
101
|
-
/**
|
|
102
|
+
/** Tools of plugins the draft's steps list that this tenant does not have. */
|
|
103
|
+
async function pluginIssues(draft) {
|
|
104
|
+
const issues = [];
|
|
105
|
+
let known = null;
|
|
106
|
+
for (const step of draft.steps) {
|
|
107
|
+
for (const id of step.type === "agent" ? step.tools : []) {
|
|
108
|
+
const named = pluginToolOf(id);
|
|
109
|
+
if (!named) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
known ??= new Set((await pluginToolsOf(currentTenant())).map((tool) => tool.id));
|
|
113
|
+
if (!known.has(id)) {
|
|
114
|
+
issues.push({
|
|
115
|
+
stepId: step.id,
|
|
116
|
+
message: `Step "${step.id}": tool "${id}" is not available here — the plugin "${named.plugin}" is not installed or has no such tool.`,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return issues;
|
|
122
|
+
}
|
|
123
|
+
/** Everything wrong with a draft: its structure, its workspace files, its project's connectors and plugins. */
|
|
102
124
|
async function checkDraft(projectId, draft, files) {
|
|
103
|
-
return [
|
|
125
|
+
return [
|
|
126
|
+
...validateWizard(draft, files),
|
|
127
|
+
...(await connectorIssues(projectId, draft)),
|
|
128
|
+
...(await pluginIssues(draft)),
|
|
129
|
+
];
|
|
104
130
|
}
|
|
105
131
|
/** Validator issues of the draft, checked against its workspace and the project's connectors. */
|
|
106
132
|
export async function draftIssues(w) {
|
|
@@ -13,6 +13,7 @@ import { browserTools } from "./browser.js";
|
|
|
13
13
|
import { connectorTools } from "./connector.js";
|
|
14
14
|
import { mailTools } from "./mail.js";
|
|
15
15
|
import { assertPublicUrl, safeFetch } from "./net-guard.js";
|
|
16
|
+
import { pluginTools } from "./plugin.js";
|
|
16
17
|
import { projectTools } from "./project.js";
|
|
17
18
|
import { clip, FileKeeper } from "./shared.js";
|
|
18
19
|
import { storeTools } from "./store.js";
|
|
@@ -95,6 +96,7 @@ export async function buildStepTools(step, ctx, resolved, uploads) {
|
|
|
95
96
|
Object.assign(tools, projectTools(ctx));
|
|
96
97
|
Object.assign(tools, mailTools(step, ctx, files));
|
|
97
98
|
Object.assign(tools, await connectorTools(step, ctx, files));
|
|
99
|
+
Object.assign(tools, await pluginTools(step, ctx));
|
|
98
100
|
const sandbox = sandboxCapabilities();
|
|
99
101
|
if (allowed.has("sandbox") && sandbox) {
|
|
100
102
|
const timeoutMs = (seconds) => Math.min((seconds ?? 120) * 1000, 600_000);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { pluginToolOf } from "@engenty-wizards/shared/definition";
|
|
2
|
+
import { createTool } from "@mastra/core/tools";
|
|
3
|
+
import { StepError } from "../engine/types.js";
|
|
4
|
+
import { loadedPlugin, pluginIdsOf } from "../plugins/registry.js";
|
|
5
|
+
import { attempt } from "./shared.js";
|
|
6
|
+
/** The model's name of a plugin's tool: `<plugin>_<tool>`, since a tool name takes no dot. */
|
|
7
|
+
export function pluginToolName(plugin, tool) {
|
|
8
|
+
return `${plugin.replaceAll("-", "_")}_${tool}`;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* The tools of plugins a step allowlists as `<plugin>.<tool>`. A step that names a tool this
|
|
12
|
+
* tenant does not have fails: the wizard was written for a runtime with that plugin.
|
|
13
|
+
*/
|
|
14
|
+
export async function pluginTools(step, ctx) {
|
|
15
|
+
const wanted = step.tools.map(pluginToolOf).filter((named) => named !== null);
|
|
16
|
+
if (!wanted.length) {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
const tools = {};
|
|
20
|
+
const has = await pluginIdsOf(ctx.tenantId);
|
|
21
|
+
for (const { plugin, tool } of wanted) {
|
|
22
|
+
const found = has.has(plugin) ? loadedPlugin(plugin)?.tools.get(tool) : undefined;
|
|
23
|
+
if (!found) {
|
|
24
|
+
throw new StepError(`Dieser Schritt braucht das Werkzeug „${plugin}.${tool}“. Das Plugin „${plugin}“ ist hier nicht installiert.`);
|
|
25
|
+
}
|
|
26
|
+
const id = pluginToolName(plugin, tool);
|
|
27
|
+
tools[id] = createTool({
|
|
28
|
+
id,
|
|
29
|
+
description: found.description,
|
|
30
|
+
inputSchema: found.inputSchema,
|
|
31
|
+
execute: (input) => attempt(async () => found.execute(input, {
|
|
32
|
+
runId: ctx.runId,
|
|
33
|
+
stepId: ctx.stepId,
|
|
34
|
+
tenantId: ctx.tenantId,
|
|
35
|
+
project: { id: ctx.project.id, name: ctx.project.name },
|
|
36
|
+
wizard: { title: ctx.def.title },
|
|
37
|
+
signal: ctx.signal,
|
|
38
|
+
emit: (message) => ctx.emit("tool", message),
|
|
39
|
+
})),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return tools;
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,n as t,t as n}from"./jsx-runtime-D3jfb0Ew.js";import{t as r}from"./preload-helper-CNEI7N0N.js";import{a as i,d as a,h as o,i as s,s as c,y as l}from"./ui-Cs6lpsmj.js";var u=e(t(),1),d=e(n(),1);function f(e){switch(e.group){case`Added`:return{label:`NEW`,dot:`bg-moss`};case`Fixed`:return{label:`FIXED`,dot:`bg-amber`};case`Changed`:return{label:`CHANGED`,dot:`bg-cobalt`};case`Performance`:return{label:`PERFORMANCE`,dot:`bg-ember`};case`Deploy`:return{label:`DEPLOY`,dot:`bg-ink-4`};case`Docs`:return{label:`DOCS`,dot:`bg-ink-4`};default:return{label:`OTHER`,dot:`bg-ink-4`}}}var p=e=>e.version?e.version.replace(/^v/,``):l(`about.unreleased`),m=e=>e.timestamp?new Date(e.timestamp*1e3).toISOString().slice(0,10):``,h=e=>e.charAt(0).toUpperCase()+e.slice(1);function g(e,t){let n=t.trim().toLowerCase();if(!n)return e;let r=[];for(let t of e){if(`${p(t)} ${m(t)}`.toLowerCase().includes(n)){r.push(t);continue}let e=t.commits.filter(e=>`${f(e).label} ${e.scope??``} ${e.message}`.toLowerCase().includes(n));e.length>0&&r.push({...t,commits:e})}return r}function _({open:e,onClose:t}){let[n,_]=(0,u.useState)(null),[v,y]=(0,u.useState)(``);(0,u.useEffect)(()=>{if(!e||n)return;let t=!1;return r(()=>import(`./changelog-03JgixQA.js`).then(e=>{t||_(e.default)}),[]),()=>{t=!0}},[e,n]),(0,u.useEffect)(()=>{e||y(``)},[e]);let b=n?g(n,v):[];return(0,d.jsxs)(s,{open:e,onClose:t,title:l(`about.changelog`),wide:!0,children:[(0,d.jsx)(`p`,{className:`-mt-3 mb-4 text-[14px] text-ink-3`,children:l(`about.changelogHint`)}),n===null?(0,d.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,d.jsx)(a,{})}):n.length===0?(0,d.jsx)(i,{children:l(`about.changelogEmpty`)}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(c,{type:`search`,value:v,placeholder:l(`about.search`),onChange:e=>y(e.target.value)}),b.length===0?(0,d.jsx)(i,{children:l(`about.noMatches`)}):null,b.map(e=>(0,d.jsxs)(`section`,{className:`mt-6`,children:[(0,d.jsxs)(`h3`,{className:`flex items-baseline gap-3 border-border-soft border-b pb-2 font-display font-semibold text-[16px]`,children:[p(e),(0,d.jsx)(`span`,{className:`font-normal font-sans text-[13px] text-ink-3 tabular-nums`,children:m(e)})]}),(0,d.jsx)(`ul`,{className:`mt-3 flex flex-col gap-2`,children:e.commits.map(e=>{let t=f(e);return(0,d.jsxs)(`li`,{className:`flex items-start gap-2.5 text-[14px]`,children:[(0,d.jsx)(`span`,{className:o(`mt-[7px] size-1.5 shrink-0 rounded-full`,t.dot)}),(0,d.jsxs)(`span`,{className:`min-w-0 text-ink-2`,children:[(0,d.jsxs)(`span`,{className:`font-semibold text-[12px] text-ink tracking-wide`,children:[t.label,e.scope?` [${e.scope}]`:``]}),` `,h(e.message),e.breaking?(0,d.jsx)(`span`,{className:`ml-1.5 rounded-full bg-rose-tint px-1.5 py-0.5 font-medium text-[12px] text-rose`,children:l(`about.breaking`)}):null]})]},e.id)})})]},e.version??`unreleased`))]})]})}export{_ as ChangelogDialog};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,n as t,t as n}from"./jsx-runtime-D3jfb0Ew.js";import{c as r,d as i,i as a,n as o,nt as s}from"./api-KMi35npD.js";import{t as c}from"./createLucideIcon-q3MZMmnf.js";import{t as l}from"./plug-CLjyCoHB.js";import{S as u,g as d,h as f,r as p,v as m}from"./outputs-COE_nvAw.js";import{r as h}from"./wand-sparkles-CKxArWPY.js";import{t as g}from"./plus-Du-Jx8aI.js";import{t as _}from"./mic-Bvz4mA2j.js";import{_ as v,d as y,h as b,o as x,y as S}from"./ui-Cs6lpsmj.js";import{l as C}from"./index-BmpnE7IO.js";var w={name:`chevron-up`,size:24,node:[[`path`,{d:`m18 15-6-6-6 6`,key:`153udz`}]]};w.node;var T=c(w),E=e(t(),1),D=!1;function O(){if(!(typeof window>`u`||D))return window.SpeechRecognition??window.webkitSpeechRecognition}var k=typeof navigator<`u`&&!!navigator.mediaDevices?.getUserMedia&&typeof MediaRecorder<`u`;function A(e,t){let n=e.trimEnd(),r=t.trim();return n&&r?`${n} ${r}`:n||r}function j(e,t){let[n,r]=(0,E.useState)(!1),[i,a]=(0,E.useState)(!1),[s,c]=(0,E.useState)(null),l=(0,E.useRef)(e);l.current=e;let u=(0,E.useRef)(t);u.current=t;let d=(0,E.useRef)(null);(0,E.useEffect)(()=>()=>d.current?.stop(),[]);let f=async()=>{let e=l.current,t;try{t=await navigator.mediaDevices.getUserMedia({audio:!0})}catch{c(`denied`);return}let n=[],i=new MediaRecorder(t);i.ondataavailable=e=>e.data.size&&n.push(e.data),i.onstop=async()=>{for(let e of t.getTracks())e.stop();d.current=null,r(!1);let s=(i.mimeType||`audio/webm`).split(`;`)[0],l=new File(n,`dictation`,{type:s});if(l.size){a(!0);try{let{text:t}=await o.upload(`/api/studio/transcribe`,l);t.trim()&&u.current(A(e,t))}catch(e){c(e.message)}finally{a(!1)}}},d.current={stop:()=>i.state!==`inactive`&&i.stop()},i.start(),r(!0)},p=e=>{let t=l.current,n=``,i=new e;i.continuous=!0,i.interimResults=!0,i.lang=v===`de`?`de-DE`:`en-US`,i.onresult=e=>{let r=``;for(let t=Math.max(0,e.resultIndex);t<e.results.length;t++){let i=e.results[t],a=i[0]?.transcript??``;i.isFinal?n=A(n,a):r+=a}u.current(A(t,A(n,r)))},i.onerror=e=>{if(e.error!==`aborted`&&e.error!==`no-speech`){if(e.error===`not-allowed`){c(`denied`);return}D=!0,k&&!n?(i.onend=null,d.current=null,f()):c(e.error)}},i.onend=()=>{d.current=null,r(!1)},d.current={stop:()=>i.stop()},i.start(),r(!0)};return{supported:!!O()||k,listening:n,processing:i,error:s,toggle:()=>{if(i)return;if(d.current){d.current.stop();return}c(null);let e=O();e?p(e):f()}}}var M=e(n(),1),N=/\.(png|jpe?g|gif|webp|avif|svg)$/i;function P(e){let t=e.filter(e=>e.type.startsWith(`image/`));return t.length?Object.fromEntries(t.map(e=>[e.name,URL.createObjectURL(e)])):void 0}function F(e){let t=e.match(/(?:^|\n\n)(?:Angehängt|Attached): ([^\n]+)$/);return t?{text:e.slice(0,t.index).trim(),names:t[1].split(`, `).filter(Boolean)}:{text:e,names:[]}}function I(e,t){if(e.name&&e.name!==`image.png`)return e;let n=e.type.split(`/`)[1]?.replace(`jpeg`,`jpg`)||`png`,r=new Date().toISOString().slice(0,19).replace(/[-:]/g,``).replace(`T`,`-`);return new File([e],`paste-${r}${t?`-${t+1}`:``}.${n}`,{type:e.type})}function L({url:e,label:t,children:n}){return(0,M.jsxs)(`div`,{className:`group relative`,title:t,children:[(0,M.jsx)(`img`,{src:e,alt:t,width:64,height:64,className:`size-16 rounded-lg bg-paper-2 object-cover ring-1 ring-border`}),n]})}function R({names:e,previews:t,fileUrl:n}){let r=e.filter(e=>t?.[e]||n&&N.test(e)),i=e.filter(e=>!r.includes(e));return(0,M.jsxs)(`div`,{className:`flex flex-col items-end gap-1.5`,children:[r.map(e=>{let r=t?.[e]??n?.(e)??``;return(0,M.jsx)(`a`,{href:r,target:`_blank`,rel:`noreferrer`,title:e,children:(0,M.jsx)(`img`,{src:r,alt:e,className:`max-h-60 w-auto max-w-full rounded-xl bg-paper-2 object-contain ring-1 ring-border`})},e)}),i.length?(0,M.jsx)(`div`,{className:`flex flex-wrap justify-end gap-1.5`,children:i.map(e=>(0,M.jsxs)(`span`,{className:`inline-flex max-w-full items-center gap-1.5 rounded-full bg-paper-2 px-2.5 py-1 text-[12px] text-ink-2`,children:[(0,M.jsx)(m,{className:`size-3 shrink-0 text-ink-4`}),(0,M.jsx)(`span`,{className:`truncate`,children:e})]},e))}):null]})}function z(e,t){let n=s(),[i,o]=(0,E.useState)([]),[c,l]=(0,E.useState)(`idle`),[u,d]=(0,E.useState)(null),[f,p]=(0,E.useState)(null),[m,h]=(0,E.useState)(null),[g,_]=(0,E.useState)(null),v=(0,E.useRef)(null);return(0,E.useEffect)(()=>{if(e){if(v.current!==e.id){v.current=e.id,o(e.messages);return}c===`idle`&&o(t=>e.messages.length>=t.length?e.messages:t)}},[e,c]),{messages:i,phase:c,activity:f,thought:m,startedAt:g,error:u,send:async(i,s=[])=>{if(!e||!(i.trim()||s.length)||c!==`idle`)return!1;if(d(null),_(Date.now()),h(null),s.length){l(`thinking`);try{for(let t of s){let n=await fetch(r(`/api/studio/wizards/${e.id}/files/${encodeURIComponent(t.name)}`),{method:`PUT`,credentials:`include`,headers:{"content-type":t.type||`application/octet-stream`},body:t});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.error??n.statusText)}}}catch(t){return d(t.message),l(`idle`),_(null),await n.invalidateQueries({queryKey:[`wizard`,e.id]}),!1}let t=`${S(`editor.attached`)}: ${s.map(e=>e.name).join(`, `)}`;i=i.trim()?`${i}\n\n${t}`:t}let u=`p-${Date.now()}`;o(e=>[...e,{id:`u-${Date.now()}`,role:`user`,content:i,previews:P(s)},{id:u,role:`assistant`,content:``,pending:!0}]),l(`thinking`),p(null);let f=!1;try{await a(`/api/studio/wizards/${e.id}/chat`,{message:i},(e,n)=>{if(e===`text`){let e=JSON.parse(n);o(t=>t.map(t=>t.id===u?{...t,content:t.content+e}:t))}else if(e===`activity`)p(JSON.parse(n));else if(e===`thought`)h(JSON.parse(n));else if(e===`building`)l(`building`);else if(e===`done`){f=!0;let e=JSON.parse(n);o(t=>t.map(t=>t.id===u?{...t,content:e.reply,changed:e.changed,pending:!1}:t)),e.changed&&t(e.draft,e.revision)}else e===`error`&&(f=!0,d(JSON.parse(n).message))}),f||d(S(`editor.chatBroken`))}catch(e){d(e.message)}finally{p(null),h(null),_(null),o(e=>e.filter(e=>!(e.id===u&&!e.content)).map(e=>({...e,pending:!1}))),l(`idle`),await n.invalidateQueries({queryKey:[`wizard`,e.id]}),await n.invalidateQueries({queryKey:[`me`]})}return!0},fileUrl:t=>r(`/api/studio/wizards/${e?.id}/files/${encodeURIComponent(t)}`)}}function B(e){let[t,n]=(0,E.useState)(()=>Date.now());return(0,E.useEffect)(()=>{if(e===null)return;n(Date.now());let t=setInterval(()=>n(Date.now()),1e3);return()=>clearInterval(t)},[e]),e===null?null:Math.max(0,Math.floor((t-e)/1e3))}function V(e){return e<60?`${e} s`:`${Math.floor(e/60)}:${String(e%60).padStart(2,`0`)} min`}function H({chat:e,thought:t,className:n,spinner:r=`size-3.5`}){let i=B(e.startedAt);return(0,M.jsxs)(`div`,{className:b(`min-w-0`,n),children:[(0,M.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,M.jsx)(y,{className:b(`shrink-0`,r)}),(0,M.jsx)(`span`,{className:`min-w-0 truncate`,children:e.activity??(e.phase===`building`?S(`editor.building`):S(`editor.thinking`))}),i===null?null:(0,M.jsx)(`span`,{className:`shrink-0 text-ink-4 tabular-nums`,children:V(i)})]}),t&&e.thought?(0,M.jsx)(`p`,{className:`mt-0.5 truncate pl-5.5 text-[12px] text-ink-4`,children:e.thought}):null]})}function U({message:e,fileUrl:t}){let{text:n,names:r}=F(e.content);return(0,M.jsxs)(`div`,{className:`ml-8 flex flex-col items-end gap-1.5 self-end`,children:[r.length?(0,M.jsx)(R,{names:r,previews:e.previews,fileUrl:t}):null,n?(0,M.jsx)(`div`,{className:`rounded-xl rounded-br-md bg-paper-2 px-4 py-2.5 text-[14px] leading-relaxed`,children:(0,M.jsx)(`span`,{className:`whitespace-pre-wrap`,children:n})}):null]})}function W({chat:e,avatar:t,hello:n=S(`editor.chatHello`),placeholder:r=S(`editor.composer`),changedLabel:a=`Ablauf aktualisiert`,compact:o,intro:s}){let[c,v]=(0,E.useState)(!1),[w,D]=(0,E.useState)(``),[O,k]=(0,E.useState)([]),A=(0,E.useRef)(null),N=(0,E.useRef)(null),P=(0,E.useRef)(null),F=j(w,D);(0,E.useEffect)(()=>{A.current?.scrollTo({top:A.current.scrollHeight,behavior:`smooth`})},[e.messages,e.phase]),(0,E.useEffect)(()=>{let e=N.current;e&&(e.style.height=`auto`,e.style.height=`${Math.min(e.scrollHeight,200)}px`)},[w]);let R=(w.trim()||O.length>0)&&e.phase===`idle`,z=e=>k(t=>[...t.filter(t=>!e.some(e=>e.name===t.name)),...e]),[B,V]=(0,E.useState)(new Map);(0,E.useEffect)(()=>{let e=new Map(O.filter(e=>e.type.startsWith(`image/`)).map(e=>[e,URL.createObjectURL(e)]));return V(e),()=>{for(let t of e.values())URL.revokeObjectURL(t)}},[O]);let W=async()=>{if(!R)return;F.listening&&F.toggle();let t={text:w,files:O};D(``),k([]),await e.send(t.text.trim(),t.files)||(D(t.text),k(t.files))},G=!o||c,K=e.messages.at(-1);return(0,M.jsxs)(`div`,{className:`flex h-full min-h-0 flex-col`,children:[o&&(K||e.error)?(0,M.jsxs)(`button`,{type:`button`,"aria-expanded":c,"aria-label":S(`editor.thread`),onClick:()=>v(e=>!e),className:`flex items-center gap-2 px-4 pt-2.5 pb-0.5 text-left text-[13px] text-ink-3 transition hover:text-ink`,children:[!(e.error||c)&&K?.pending?(0,M.jsx)(H,{chat:e,className:`flex-1`}):(0,M.jsx)(`span`,{className:b(`min-w-0 flex-1 truncate`,e.error&&`text-rose`),children:e.error??(c?S(`editor.thread`):K?.content)}),c?(0,M.jsx)(h,{className:`size-4 shrink-0`}):(0,M.jsx)(T,{className:`size-4 shrink-0`})]}):null,(0,M.jsxs)(`div`,{ref:A,className:b(`min-h-0 flex-1 overflow-y-auto px-5 py-5`,!G&&`hidden`),children:[e.messages.length===0?s??(0,M.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,M.jsx)(i,{kind:t,size:32,interactive:!1}),(0,M.jsx)(`p`,{className:`pt-1 text-[14px] text-ink-2 leading-relaxed`,children:n})]}):null,(0,M.jsx)(`div`,{className:`flex flex-col gap-4`,children:e.messages.map(n=>n.role===`user`?(0,M.jsx)(U,{message:n,fileUrl:e.fileUrl},n.id):(0,M.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,M.jsx)(`div`,{className:`shrink-0`,children:(0,M.jsx)(i,{kind:t,size:28,interactive:!1})}),(0,M.jsxs)(`div`,{className:`min-w-0 pt-0.5 text-[14px]`,children:[n.source===`mcp`?(0,M.jsxs)(`div`,{className:`mb-1 inline-flex items-center gap-1.5 text-[12px] text-ink-3`,children:[(0,M.jsx)(l,{className:`size-3`}),` `,S(`editor.viaClient`,{client:n.client??`MCP`})]}):null,n.content?(0,M.jsx)(p,{text:n.content,className:`text-[14px]`}):null,n.pending?(0,M.jsx)(H,{chat:e,thought:!0,className:`mt-1 text-[13px] text-ink-3`}):null,n.changed?(0,M.jsxs)(`div`,{className:`mt-2 inline-flex items-center gap-1.5 rounded-full bg-ember-tint px-2.5 py-0.5 text-[12px] text-ember-strong`,children:[(0,M.jsx)(d,{className:`size-3`}),` `,a]}):null]})]},n.id))}),e.error?(0,M.jsx)(`div`,{className:`mt-4 rounded-lg bg-rose-tint px-3 py-2 text-[13px] text-rose`,children:e.error}):null]}),(0,M.jsxs)(`div`,{className:o?`p-2`:`p-3`,children:[(0,M.jsxs)(`div`,{className:`rounded-xl bg-card p-1.5 shadow-soft ring-1 ring-border focus-within:ring-focus`,children:[B.size?(0,M.jsx)(`div`,{className:`flex flex-wrap gap-2 px-1 pt-1 pb-1.5`,children:O.map((e,t)=>{let n=B.get(e);return n?(0,M.jsx)(L,{url:n,label:e.name,children:(0,M.jsx)(`button`,{type:`button`,"aria-label":S(`editor.detach`),onClick:()=>k(e=>e.filter((e,n)=>n!==t)),className:`-top-1.5 -right-1.5 absolute flex size-5 items-center justify-center rounded-full bg-ink text-paper opacity-0 shadow-soft transition focus-visible:opacity-100 group-hover:opacity-100`,children:(0,M.jsx)(C,{className:`size-3`})})},`${e.name}-${t}`):null})}):null,O.some(e=>!B.has(e))?(0,M.jsx)(`ul`,{className:`flex flex-wrap gap-1.5 px-1 pt-1 pb-1.5`,children:O.map((e,t)=>B.has(e)?null:(0,M.jsxs)(`li`,{className:`inline-flex max-w-full items-center gap-1.5 rounded-full bg-paper-2 py-1 pr-1 pl-2.5 text-[12px] text-ink-2`,children:[(0,M.jsx)(m,{className:`size-3 shrink-0 text-ink-4`}),(0,M.jsx)(`span`,{className:`truncate`,children:e.name}),(0,M.jsx)(`button`,{type:`button`,"aria-label":S(`editor.detach`),onClick:()=>k(e=>e.filter((e,n)=>n!==t)),className:`inline-flex size-5 shrink-0 items-center justify-center rounded-full text-ink-3 hover:bg-paper-3 hover:text-ink`,children:(0,M.jsx)(C,{className:`size-3`})})]},`${e.name}-${t}`))}):null,(0,M.jsxs)(`div`,{className:`flex items-end gap-1`,children:[(0,M.jsx)(x,{label:S(`editor.attach`),onClick:()=>P.current?.click(),children:(0,M.jsx)(g,{className:`size-4`})}),(0,M.jsx)(`input`,{ref:P,type:`file`,multiple:!0,hidden:!0,onChange:e=>{let t=Array.from(e.target.files??[]);e.target.value=``,z(t)}}),(0,M.jsx)(`textarea`,{ref:N,rows:1,value:w,onChange:e=>D(e.target.value),onPaste:e=>{let t=Array.from(e.clipboardData.files);t.length&&(e.preventDefault(),z(t.map(I)))},onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),W())},placeholder:F.listening?S(`editor.listening`):r,className:`max-h-[200px] min-h-[40px] flex-1 resize-none bg-transparent px-1.5 py-2 text-[14px] outline-none placeholder:text-ink-4`}),F.supported?(0,M.jsx)(x,{label:F.processing?S(`editor.transcribing`):F.listening?S(`editor.voiceStop`):S(`editor.voice`),"aria-pressed":F.listening,disabled:F.processing,onClick:F.toggle,className:b(F.listening&&`bg-rose-tint text-rose hover:bg-rose-tint hover:text-rose`),children:F.processing?(0,M.jsx)(y,{className:`size-4`}):F.listening?(0,M.jsx)(f,{className:`size-3.5 animate-pulse-dot fill-current`}):(0,M.jsx)(_,{className:`size-4`})}):null,(0,M.jsx)(`button`,{type:`button`,onClick:()=>void W(),disabled:!R,className:b(`inline-flex size-9 shrink-0 items-center justify-center rounded-full transition`,R?`bg-primary text-primary-foreground`:`bg-paper-2 text-ink-4`),"aria-label":`Send`,children:(0,M.jsx)(u,{className:`size-4`})})]})]}),F.error?(0,M.jsx)(`p`,{className:`mt-2 px-1 text-[12px] text-rose`,children:F.error===`denied`?S(`editor.micDenied`):F.error}):null]})]})}export{z as i,H as n,P as r,W as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,n as t,t as n}from"./jsx-runtime-D3jfb0Ew.js";import{t as r}from"./preload-helper-CNEI7N0N.js";import{t as i}from"./external-link-MAL7vJYj.js";import{_ as a,a as o,d as s,i as c,s as l,y as u}from"./ui-Cs6lpsmj.js";var d=e(t(),1),f=[{name:`engenty wizards`,description:{de:`KI-Wizards aus einer Beschreibung, mit einem Link geteilt.`,en:`AI wizards built from a description, shared with a link.`},homepage:`https://github.com/engenty/engenty-wizards`,license:`FSL-1.1-MIT`},{name:`engenty`,description:{de:`Konnektoren, Datentabellen, Suche und die Engenties stammen aus dem engenty-Framework.`,en:`Connectors, data tables, search and the engenties come from the engenty framework.`},homepage:`https://github.com/engenty/engenty`,license:`FSL-1.1-MIT`}],p=[{name:`Mastra`,description:{de:`Agent-Framework hinter den KI-Schritten.`,en:`Agent framework behind the AI steps.`},homepage:`https://github.com/mastra-ai/mastra`,license:`Apache-2.0`},{name:`AI SDK`,description:{de:`Modell-Aufrufe für Text, Bild, Video und Sprache.`,en:`Model calls for text, image, video and speech.`},homepage:`https://github.com/vercel/ai`,license:`Apache-2.0`},{name:`Model Context Protocol`,description:{de:`MCP-Server zum Bauen von Wizards, MCP-Client für Werkzeuge der Schritte.`,en:`MCP server for building wizards, MCP client for the steps' tools.`},homepage:`https://github.com/modelcontextprotocol/typescript-sdk`,license:`MIT`},{name:`Hono`,description:{de:`HTTP-API der Runtime.`,en:`The runtime's HTTP API.`},homepage:`https://github.com/honojs/hono`,license:`MIT`},{name:`Drizzle ORM`,description:{de:`Schema und Migrationen der Datenbanken.`,en:`Schema and migrations of the databases.`},homepage:`https://github.com/drizzle-team/drizzle-orm`,license:`Apache-2.0`},{name:`libSQL`,description:{de:`Eine Datenbank je Mandant, lokal als Datei oder bei Turso.`,en:`One database per tenant, a local file or at Turso.`},homepage:`https://github.com/tursodatabase/libsql`,license:`MIT`},{name:`Playwright`,description:{de:`Browser-Schritte sowie PDF- und PNG-Export.`,en:`Browser steps and the PDF and PNG export.`},homepage:`https://github.com/microsoft/playwright`,license:`Apache-2.0`},{name:`agentOS`,description:{de:`Sandbox für Code-Schritte ohne Docker.`,en:`Sandbox for code steps without Docker.`},homepage:`https://github.com/rivet-dev/agentos`,license:`Apache-2.0`},{name:`React`,description:{de:`UI-Bibliothek der Web-App.`,en:`UI library of the web app.`},homepage:`https://github.com/facebook/react`,license:`MIT`},{name:`Vite`,description:{de:`Build-Werkzeug der Web-App.`,en:`Build tool of the web app.`},homepage:`https://github.com/vitejs/vite`,license:`MIT`},{name:`Tailwind CSS`,description:{de:`Styling der Oberfläche.`,en:`Styling of the interface.`},homepage:`https://github.com/tailwindlabs/tailwindcss`,license:`MIT`},{name:`React Flow`,description:{de:`Das Diagramm der Schritte im Editor.`,en:`The diagram of steps in the editor.`},homepage:`https://github.com/xyflow/xyflow`,license:`MIT`},{name:`TanStack Query`,description:{de:`Server-Daten in der Web-App.`,en:`Server data in the web app.`},homepage:`https://github.com/TanStack/query`,license:`MIT`},{name:`xterm.js`,description:{de:`Das Terminal auf der Seite, in dem sich KI-Clients anmelden.`,en:`The terminal on the page where AI clients sign in.`},homepage:`https://github.com/xtermjs/xterm.js`,license:`MIT`},{name:`Lucide`,description:{de:`Icons.`,en:`Icons.`},homepage:`https://github.com/lucide-icons/lucide`,license:`ISC`},{name:`Geist & Geist Mono`,description:{de:`Schrift der Oberfläche.`,en:`Typeface of the interface.`},homepage:`https://github.com/vercel/geist-font`,license:`OFL-1.1`},{name:`Space Grotesk`,description:{de:`Schrift der Überschriften.`,en:`Typeface of the headings.`},homepage:`https://github.com/floriankarsten/space-grotesk`,license:`OFL-1.1`},{name:`git-cliff`,description:{de:`Erzeugt den Changelog aus den Commits.`,en:`Generates the changelog from the commits.`},homepage:`https://github.com/orhun/git-cliff`,license:`MIT OR Apache-2.0`}],m=e(n(),1),h=(e,...t)=>t.some(t=>t?.toLowerCase().includes(e));function g({name:e,homepage:t,version:n,license:r,description:a}){return(0,m.jsxs)(`li`,{className:`py-2.5`,children:[(0,m.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-x-2.5 gap-y-0.5`,children:[t?(0,m.jsxs)(`a`,{href:t,target:`_blank`,rel:`noreferrer`,className:`inline-flex items-center gap-1 font-medium text-[14px] text-ink underline-offset-4 hover:underline`,children:[e,(0,m.jsx)(i,{"aria-hidden":!0,className:`size-3 text-ink-4`})]}):(0,m.jsx)(`span`,{className:`font-medium text-[14px] text-ink`,children:e}),n?(0,m.jsx)(`span`,{className:`text-[12px] text-ink-3 tabular-nums`,children:n}):null,(0,m.jsx)(`span`,{className:`text-[12px] text-ink-3`,children:r})]}),a?(0,m.jsx)(`p`,{className:`mt-0.5 text-[13px] text-ink-3`,children:a}):null]})}function _({title:e,hint:t,children:n}){return(0,m.jsxs)(`section`,{className:`mt-6`,children:[(0,m.jsx)(`h3`,{className:`border-border-soft border-b pb-2 font-display font-semibold text-[16px]`,children:e}),t?(0,m.jsx)(`p`,{className:`mt-2 text-[13px] text-ink-3`,children:t}):null,n]})}function v({credits:e}){return(0,m.jsx)(`ul`,{className:`divide-y divide-border-soft`,children:e.map(e=>(0,m.jsx)(g,{name:e.name,homepage:e.homepage,license:e.license,description:e.description[a]},e.name))})}function y({label:e,packages:t}){return(0,m.jsxs)(`div`,{className:`mt-4`,children:[(0,m.jsx)(`h4`,{className:`font-medium text-[12px] text-ink-3 tracking-wide`,children:e}),(0,m.jsx)(`ul`,{className:`divide-y divide-border-soft`,children:t.map(e=>(0,m.jsx)(g,{...e},e.name))})]})}function b({open:e,onClose:t}){let[n,i]=(0,d.useState)(null),[a,g]=(0,d.useState)(``);(0,d.useEffect)(()=>{if(!e||n)return;let t=!1;return r(()=>import(`./oss-credits-roB62QJu.js`).then(e=>{t||i(e.default)}),[]),()=>{t=!0}},[e,n]),(0,d.useEffect)(()=>{e||g(``)},[e]);let b=a.trim().toLowerCase(),x=e=>b?e.filter(e=>h(b,e.name,e.license,e.description.de,e.description.en)):e,S=e=>b?e.filter(e=>h(b,e.name,e.license,e.version)):e,C=x(f),w=x(p),T=n?[{id:`shared`,label:u(`about.creditsShared`),packages:S(n.shared)},...n.groups.map(e=>({id:e.id,label:e.label,packages:S(e.packages)}))].filter(e=>e.packages.length>0):[],E=C.length===0&&w.length===0&&T.length===0;return(0,m.jsxs)(c,{open:e,onClose:t,title:u(`about.credits`),wide:!0,children:[(0,m.jsx)(`p`,{className:`-mt-3 mb-4 text-[14px] text-ink-3`,children:u(`about.creditsHint`)}),(0,m.jsx)(l,{type:`search`,value:a,placeholder:u(`about.search`),onChange:e=>g(e.target.value)}),C.length>0?(0,m.jsx)(_,{title:u(`about.creditsProduct`),children:(0,m.jsx)(v,{credits:C})}):null,w.length>0?(0,m.jsx)(_,{title:u(`about.creditsBuiltWith`),children:(0,m.jsx)(v,{credits:w})}):null,n===null?(0,m.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,m.jsx)(s,{})}):T.length>0?(0,m.jsx)(_,{title:u(`about.creditsDeps`),hint:b?void 0:u(`about.creditsDepsHint`),children:T.map(e=>(0,m.jsx)(y,{label:e.label,packages:e.packages},e.id))}):null,n!==null&&E?(0,m.jsx)(o,{children:u(`about.noMatches`)}):null]})}export{b as CreditsDialog};
|