wizards 0.2.26 → 0.2.28
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/apps/runtime/dist/agents/project-assistant.js +10 -1
- package/apps/runtime/dist/authoring/guide.js +7 -3
- package/apps/runtime/dist/connectors/plugin-connections.js +248 -0
- package/apps/runtime/dist/db/migrations/tenant/0010_plugin_connection.sql +15 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0010_snapshot.json +2942 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +7 -0
- package/apps/runtime/dist/db/schema.js +21 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/calendar.js +25 -3
- package/apps/runtime/dist/engenty/connections-microsoft/outlook.js +29 -1
- package/apps/runtime/dist/engine/input.js +10 -1
- package/apps/runtime/dist/mcp/tools.js +5 -2
- package/apps/runtime/dist/plugins/loader.js +22 -1
- package/apps/runtime/dist/plugins/registry.js +10 -0
- package/apps/runtime/dist/routes/marketplace.js +2 -1
- package/apps/runtime/dist/routes/runs.js +11 -3
- package/apps/runtime/dist/routes/studio.js +3 -1
- package/apps/runtime/dist/services/marketplace.js +167 -5
- package/apps/runtime/dist/services/runs.js +43 -15
- package/apps/runtime/dist/services/wizards.js +4 -2
- package/apps/runtime/dist/tools/plugin.js +29 -1
- package/apps/web/dist/assets/Account-CVMSZTCv.js +1 -0
- package/apps/web/dist/assets/{ChangelogDialog-CdtQWq0m.js → ChangelogDialog-3N1CgtWP.js} +1 -1
- package/apps/web/dist/assets/CreditsDialog-BW-RETl-.js +1 -0
- package/apps/web/dist/assets/EditorPage-DnuHM3nW.js +3 -0
- package/apps/web/dist/assets/{FlowPreview-IZcNrBJi.js → FlowPreview-Ds6ul7-N.js} +1 -1
- package/apps/web/dist/assets/{Harness-Cj-k02TA.js → Harness-D-QoXcSe.js} +2 -2
- package/apps/web/dist/assets/HomePage-Ch0HlwVX.js +1 -0
- package/apps/web/dist/assets/ImportWizard-DVcYcB6l.js +1 -0
- package/apps/web/dist/assets/LocalRuntime-D7bzT40S.js +1 -0
- package/apps/web/dist/assets/NewWizardPage-DvA6AX7D.js +2 -0
- package/apps/web/dist/assets/ProjectPage-BWAISSfX.js +2 -0
- package/apps/web/dist/assets/PublicRunner-D2bd95TR.js +1 -0
- package/apps/web/dist/assets/RunDrawer-DkOCgXAR.js +4 -0
- package/apps/web/dist/assets/RunnerView-DF5uW_95.js +2 -0
- package/apps/web/dist/assets/SettingsPage-CMTGFXit.js +1 -0
- package/apps/web/dist/assets/SetupPage-BaT-VqIc.js +1 -0
- package/apps/web/dist/assets/{SharePage-70niRKaO.js → SharePage-COKOsuvD.js} +1 -1
- package/apps/web/dist/assets/arrow-right-hy38IBRU.js +1 -0
- package/apps/web/dist/assets/changelog-C8wFW63z.js +1 -0
- package/apps/web/dist/assets/circle-alert-BG9P3ewL.js +1 -0
- package/apps/web/dist/assets/definition-BiUSuZN5.js +1 -0
- package/apps/web/dist/assets/esm-0rdZWuyu.js +7 -0
- package/apps/web/dist/assets/external-link-BwCtn1nW.js +1 -0
- package/apps/web/dist/assets/image-DG4q2P1H.js +1 -0
- package/apps/web/dist/assets/index-BOp2fz-2.css +1 -0
- package/apps/web/dist/assets/index-DHM9S48l.js +78 -0
- package/apps/web/dist/assets/lock-DH_BntP_.js +1 -0
- package/apps/web/dist/assets/meta-DI0ahJ_z.js +1 -0
- package/apps/web/dist/assets/pen-line-B1dsy3Sr.js +1 -0
- package/apps/web/dist/assets/refresh-cw-B9M1g3SH.js +1 -0
- package/apps/web/dist/assets/settings-menu-DOjgaq6J.js +1 -0
- package/apps/web/dist/assets/star-axQV_3EC.js +1 -0
- package/apps/web/dist/assets/surface-BE-3Z1DP.js +56 -0
- package/apps/web/dist/assets/trash-3S1_XpVa.js +1 -0
- package/apps/web/dist/assets/ui-BZ01zr3i.js +9 -0
- package/apps/web/dist/assets/upload-U0i8fAW3.js +1 -0
- package/apps/web/dist/assets/video-Db4o719f.js +1 -0
- package/apps/web/dist/assets/volume-2-6f7qN_LM.js +1 -0
- package/apps/web/dist/assets/wand-sparkles-MelvBtiK.js +1 -0
- package/apps/web/dist/index.html +4 -5
- package/apps/web/dist/mcp/flow.html +57 -57
- package/node_modules/@engenty-wizards/plugin-sdk/dist/index.d.ts +85 -0
- package/node_modules/@engenty-wizards/plugin-sdk/dist/studio.d.ts +23 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +28 -1
- package/node_modules/@engenty-wizards/shared/dist/definition.js +85 -5
- package/node_modules/@engenty-wizards/shared/dist/marketplace-search.js +4 -1
- package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +43 -1
- package/node_modules/@engenty-wizards/shared/dist/marketplace.js +27 -0
- package/package.json +1 -1
- package/apps/web/dist/assets/Account-Cnksw5Ea.js +0 -1
- package/apps/web/dist/assets/CreditsDialog-Ti43boCN.js +0 -1
- package/apps/web/dist/assets/EditorPage-N7EzlRSj.js +0 -3
- package/apps/web/dist/assets/HomePage-bjdKkt84.js +0 -1
- package/apps/web/dist/assets/ImportWizard-DagFXYPM.js +0 -1
- package/apps/web/dist/assets/LocalRuntime-Boi_zqQJ.js +0 -1
- package/apps/web/dist/assets/NewWizardPage-DO5J8OpZ.js +0 -2
- package/apps/web/dist/assets/ProjectPage-DdG9wYsd.js +0 -2
- package/apps/web/dist/assets/PublicRunner-B4ts9rT6.js +0 -1
- package/apps/web/dist/assets/RunDrawer-LnVfCiYO.js +0 -4
- package/apps/web/dist/assets/RunnerView-DwffK7AA.js +0 -70
- package/apps/web/dist/assets/SettingsPage-Cyx_jTlp.js +0 -1
- package/apps/web/dist/assets/SetupPage-CBDD4rpC.js +0 -1
- package/apps/web/dist/assets/api-C4M6cbpW.js +0 -10
- package/apps/web/dist/assets/arrow-right-6FyN3e7D.js +0 -1
- package/apps/web/dist/assets/changelog-COyL1B5X.js +0 -1
- package/apps/web/dist/assets/check-CUpby_J9.js +0 -1
- package/apps/web/dist/assets/chevron-down-DymW-2BP.js +0 -1
- package/apps/web/dist/assets/circle-alert-D2SCwFT-.js +0 -1
- package/apps/web/dist/assets/createLucideIcon-q3MZMmnf.js +0 -1
- package/apps/web/dist/assets/definition-DoCLtZZL.js +0 -55
- package/apps/web/dist/assets/esm-CfW8Rmtq.js +0 -7
- package/apps/web/dist/assets/external-link-MAL7vJYj.js +0 -1
- package/apps/web/dist/assets/image-CC_2mJd6.js +0 -1
- package/apps/web/dist/assets/index-CJ0YJ5HC.css +0 -1
- package/apps/web/dist/assets/index-DMKXnSf-.js +0 -10
- package/apps/web/dist/assets/lock-DZL2N67v.js +0 -1
- package/apps/web/dist/assets/meta-6jZygxJq.js +0 -1
- package/apps/web/dist/assets/pen-line-NK46C_nG.js +0 -1
- package/apps/web/dist/assets/plus-Du-Jx8aI.js +0 -1
- package/apps/web/dist/assets/refresh-cw-BNtHis1x.js +0 -1
- package/apps/web/dist/assets/settings-menu-Dph4yXbO.js +0 -1
- package/apps/web/dist/assets/star-UHmZXpjA.js +0 -1
- package/apps/web/dist/assets/trash-0IafyhZB.js +0 -1
- package/apps/web/dist/assets/ui-BS348L4M.js +0 -1
- package/apps/web/dist/assets/upload-DNRENWzQ.js +0 -1
- package/apps/web/dist/assets/video-9fDPRPCv.js +0 -1
- package/apps/web/dist/assets/volume-2-DE67_rue.js +0 -1
- package/apps/web/dist/assets/wand-sparkles-IEd4jkyn.js +0 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { statSync } from "node:fs";
|
|
1
3
|
import { DEFINITION_VERSION, readable, wizardSchema, } from "@engenty-wizards/shared/definition";
|
|
2
|
-
import { MARKETPLACE_LANGS, } from "@engenty-wizards/shared/marketplace";
|
|
4
|
+
import { capabilitiesOf, costTierOf, effortOf, formatsOf, MARKETPLACE_LANGS, pluginsOf, } from "@engenty-wizards/shared/marketplace";
|
|
3
5
|
import { wizardOutline } from "@engenty-wizards/shared/marketplace-entry";
|
|
4
6
|
import { searchEntries } from "@engenty-wizards/shared/marketplace-search";
|
|
5
7
|
import { and, eq, inArray, notInArray } from "drizzle-orm";
|
|
@@ -9,14 +11,19 @@ import { missingCapabilities, optionalCapabilities, stepsWithoutModel, } from ".
|
|
|
9
11
|
import { env } from "../env.js";
|
|
10
12
|
import { managed } from "../manage.js";
|
|
11
13
|
import { classCatalog, imageCostUsd, tokenCostUsd, videoCostUsd, WEB_SEARCH_COST_USD, } from "../models.js";
|
|
14
|
+
import { pluginIdsOf, pluginStartersOf } from "../plugins/registry.js";
|
|
12
15
|
import { readSetting, writeSetting } from "../settings.js";
|
|
13
|
-
import { LOCAL_TENANT } from "../tenants/tenant.js";
|
|
16
|
+
import { currentTenant, LOCAL_TENANT } from "../tenants/tenant.js";
|
|
14
17
|
import { ServiceError } from "./errors.js";
|
|
15
18
|
/**
|
|
16
19
|
* The marketplace is an app of its own; this runtime is one of its clients
|
|
17
20
|
* (docs/marketplace-contract.md). It searches the marketplace live and starts wizards from its
|
|
18
21
|
* entries. Its starters and what people starred are kept in the control database, so the list
|
|
19
22
|
* and starting a wizard work without a connection too.
|
|
23
|
+
*
|
|
24
|
+
* Beside them stand the starters the tenant's plugins bring (docs/content/dev/plugins/starters.md),
|
|
25
|
+
* listed first and never fetched. They are known as `<plugin id>.<starter id>`; a marketplace
|
|
26
|
+
* entry's id has no dot, so the two never meet.
|
|
20
27
|
*/
|
|
21
28
|
export const asLang = (raw) => MARKETPLACE_LANGS.includes(raw ?? "") ? raw : "de";
|
|
22
29
|
/** A search waits this long for the marketplace; then it searches what is kept here. */
|
|
@@ -84,6 +91,94 @@ function keptItem(e, lang) {
|
|
|
84
91
|
const text = textIn(e, lang);
|
|
85
92
|
return text ? { ...keptSummary(e, lang), definition: text.definition, files: e.files } : null;
|
|
86
93
|
}
|
|
94
|
+
// --- the plugins' starters ------------------------------------------------------------------
|
|
95
|
+
/** One of the starters the tenant's plugins bring, by its id; undefined for any other id. */
|
|
96
|
+
async function pluginStarter(id) {
|
|
97
|
+
if (!id.includes(".")) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
return (await pluginStartersOf(currentTenant())).find((s) => s.id === id);
|
|
101
|
+
}
|
|
102
|
+
/** A plugin's starter as the marketplace lists an entry, read from its definition. */
|
|
103
|
+
function pluginSummary({ id, plugin, starter }) {
|
|
104
|
+
const definition = starter.definition;
|
|
105
|
+
const { name, version } = plugin.source.manifest;
|
|
106
|
+
const capabilities = capabilitiesOf(definition);
|
|
107
|
+
const changed = statSync(plugin.source.entry ?? plugin.source.root, { throwIfNoEntry: false });
|
|
108
|
+
return {
|
|
109
|
+
id,
|
|
110
|
+
revision: 0,
|
|
111
|
+
hash: createHash("sha256")
|
|
112
|
+
.update(`${version}\n${JSON.stringify(definition)}`)
|
|
113
|
+
.digest("hex")
|
|
114
|
+
.slice(0, 16),
|
|
115
|
+
updatedAt: (changed?.mtime ?? new Date()).toISOString(),
|
|
116
|
+
starter: true,
|
|
117
|
+
language: starter.language ?? "de",
|
|
118
|
+
title: starter.title,
|
|
119
|
+
pitch: starter.description,
|
|
120
|
+
// Found by the plugin's name as well: "Termine" finds the appointment plugin's starters.
|
|
121
|
+
terms: [name],
|
|
122
|
+
avatar: definition.avatar,
|
|
123
|
+
formats: formatsOf(definition),
|
|
124
|
+
industries: ["any"],
|
|
125
|
+
useCases: [],
|
|
126
|
+
capabilities,
|
|
127
|
+
effort: effortOf(definition),
|
|
128
|
+
costTier: costTierOf(capabilities),
|
|
129
|
+
steps: definition.steps.length,
|
|
130
|
+
version: definition.version,
|
|
131
|
+
plugins: [plugin.source.id],
|
|
132
|
+
plan: "pro",
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/** A plugin's starter as this app shows it: never starred, and marked with its plugin. */
|
|
136
|
+
function pluginEntry(found, unavailable) {
|
|
137
|
+
const { id, name } = found.plugin.source.manifest;
|
|
138
|
+
return {
|
|
139
|
+
...asEntry(pluginSummary(found), new Set(), unavailable, optionalOf(found.starter.definition)),
|
|
140
|
+
plugin: { id, name },
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/** Two searches' counts per option, added up. */
|
|
144
|
+
function addFacets(a, b) {
|
|
145
|
+
const add = (x = {}, y = {}) => {
|
|
146
|
+
const out = { ...x };
|
|
147
|
+
for (const [key, n] of Object.entries(y)) {
|
|
148
|
+
out[key] = (out[key] ?? 0) + n;
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
};
|
|
152
|
+
return {
|
|
153
|
+
useCase: add(a.useCase, b.useCase),
|
|
154
|
+
industry: add(a.industry, b.industry),
|
|
155
|
+
format: add(a.format, b.format),
|
|
156
|
+
capability: add(a.capability, b.capability),
|
|
157
|
+
plan: add(a.plan, b.plan),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* The marketplace's entries as this tenant sees them: an entry that stands for a starter of a
|
|
162
|
+
* plugin it has is left out (the plugin's own is listed), and the others say which plugins they
|
|
163
|
+
* need that it does not have.
|
|
164
|
+
*/
|
|
165
|
+
async function withPlugins(entries) {
|
|
166
|
+
if (!entries.some((e) => e.plugins?.length || e.pluginStarter)) {
|
|
167
|
+
return entries;
|
|
168
|
+
}
|
|
169
|
+
const tenant = currentTenant();
|
|
170
|
+
const [have, starters] = await Promise.all([
|
|
171
|
+
pluginIdsOf(tenant),
|
|
172
|
+
pluginStartersOf(tenant).then((list) => new Set(list.map((s) => s.id))),
|
|
173
|
+
]);
|
|
174
|
+
return entries.flatMap((e) => {
|
|
175
|
+
if (e.pluginStarter && starters.has(e.pluginStarter)) {
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
const needs = (e.plugins ?? []).filter((id) => !have.has(id));
|
|
179
|
+
return [needs.length ? { ...e, needs } : e];
|
|
180
|
+
});
|
|
181
|
+
}
|
|
87
182
|
// --- searching -----------------------------------------------------------------------------
|
|
88
183
|
/** A summary as this app shows it: whether it can read and run it, and whether it is starred. */
|
|
89
184
|
function asEntry(summary, starred, unavailable, optional = new Set()) {
|
|
@@ -120,8 +215,43 @@ async function keptOptional(ids, lang, unavailable) {
|
|
|
120
215
|
}
|
|
121
216
|
return out;
|
|
122
217
|
}
|
|
123
|
-
/**
|
|
218
|
+
/**
|
|
219
|
+
* Searches the tenant's plugins' starters and the marketplace, in that order: a page holds the
|
|
220
|
+
* plugins' starters the words and filters find, then the marketplace's entries.
|
|
221
|
+
*/
|
|
124
222
|
export async function searchMarketplace(search) {
|
|
223
|
+
const { q = "", starred, limit = 60, offset = 0, lang: _lang, ...filters } = search;
|
|
224
|
+
const own = starred ? [] : await pluginStartersOf(currentTenant());
|
|
225
|
+
if (!own.length) {
|
|
226
|
+
return searchListed(search);
|
|
227
|
+
}
|
|
228
|
+
const byId = new Map(own.map((s) => [s.id, s]));
|
|
229
|
+
const found = searchEntries(own.map(pluginSummary), q, filters, { limit: own.length });
|
|
230
|
+
const shown = found.entries.slice(offset, offset + limit);
|
|
231
|
+
// The marketplace fills what is left of the page, and counts from where its entries begin.
|
|
232
|
+
const room = limit - shown.length;
|
|
233
|
+
const listed = await searchListed({
|
|
234
|
+
...search,
|
|
235
|
+
limit: Math.max(1, room),
|
|
236
|
+
offset: Math.max(0, offset - found.total),
|
|
237
|
+
});
|
|
238
|
+
const unavailable = new Set(listed.unavailable);
|
|
239
|
+
return {
|
|
240
|
+
...listed,
|
|
241
|
+
entries: [
|
|
242
|
+
...shown.flatMap((e) => {
|
|
243
|
+
const entry = byId.get(e.id);
|
|
244
|
+
return entry ? [pluginEntry(entry, unavailable)] : [];
|
|
245
|
+
}),
|
|
246
|
+
...listed.entries.slice(0, room),
|
|
247
|
+
],
|
|
248
|
+
total: found.total + listed.total,
|
|
249
|
+
all: own.length + listed.all,
|
|
250
|
+
facets: addFacets(listed.facets, found.facets),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/** Searches the marketplace; without an answer, what is kept here, scored the same way. */
|
|
254
|
+
async function searchListed(search) {
|
|
125
255
|
const { q = "", lang, starred: onlyStarred, limit = 60, offset = 0, ...filters } = search;
|
|
126
256
|
const stars = await starredIds();
|
|
127
257
|
const starred = new Set(stars);
|
|
@@ -147,7 +277,7 @@ export async function searchMarketplace(search) {
|
|
|
147
277
|
const optional = await keptOptional(remote.entries.map((e) => e.id), lang, unavailable);
|
|
148
278
|
return {
|
|
149
279
|
...remote,
|
|
150
|
-
entries: remote.entries.map((e) => asEntry(e, starred, unavailable, optional.get(e.id))),
|
|
280
|
+
entries: await withPlugins(remote.entries.map((e) => asEntry(e, starred, unavailable, optional.get(e.id)))),
|
|
151
281
|
offline: false,
|
|
152
282
|
unavailable: [...unavailable],
|
|
153
283
|
};
|
|
@@ -159,7 +289,7 @@ export async function searchMarketplace(search) {
|
|
|
159
289
|
const optional = await keptOptional(page.entries.map((e) => e.id), lang, unavailable);
|
|
160
290
|
return {
|
|
161
291
|
...page,
|
|
162
|
-
entries: page.entries.map((e) => asEntry(e, starred, unavailable, optional.get(e.id))),
|
|
292
|
+
entries: await withPlugins(page.entries.map((e) => asEntry(e, starred, unavailable, optional.get(e.id)))),
|
|
163
293
|
offline: true,
|
|
164
294
|
unavailable: [...unavailable],
|
|
165
295
|
};
|
|
@@ -217,6 +347,15 @@ async function priced(definition) {
|
|
|
217
347
|
}
|
|
218
348
|
/** An entry in a language with its wizard read against this app; null where there is none. */
|
|
219
349
|
export async function marketplaceDetail(id, lang) {
|
|
350
|
+
const own = await pluginStarter(id);
|
|
351
|
+
if (own) {
|
|
352
|
+
const definition = own.starter.definition;
|
|
353
|
+
return {
|
|
354
|
+
...pluginEntry(own, await missingCapabilities()),
|
|
355
|
+
credits: await priced(definition),
|
|
356
|
+
...wizardOutline(definition, Object.keys(own.starter.files ?? {}), lang),
|
|
357
|
+
};
|
|
358
|
+
}
|
|
220
359
|
const found = await fetchItem(id, lang);
|
|
221
360
|
if (!found) {
|
|
222
361
|
return null;
|
|
@@ -242,6 +381,23 @@ export async function marketplaceDetail(id, lang) {
|
|
|
242
381
|
}
|
|
243
382
|
/** An entry's wizard and workspace in a language: what a wizard is made from. */
|
|
244
383
|
export async function marketplaceWizard(id, lang) {
|
|
384
|
+
const own = await pluginStarter(id);
|
|
385
|
+
if (own) {
|
|
386
|
+
// A plugin's starter is in its one language, whatever is asked for.
|
|
387
|
+
const { starter, plugin } = own;
|
|
388
|
+
return {
|
|
389
|
+
id,
|
|
390
|
+
revision: null,
|
|
391
|
+
plugin: plugin.source.id,
|
|
392
|
+
title: starter.title,
|
|
393
|
+
language: starter.language ?? "de",
|
|
394
|
+
definition: structuredClone(starter.definition),
|
|
395
|
+
files: Object.fromEntries(Object.entries(starter.files ?? {}).map(([path, data]) => [
|
|
396
|
+
path,
|
|
397
|
+
typeof data === "string" ? Buffer.from(data, "utf8") : Buffer.from(data),
|
|
398
|
+
])),
|
|
399
|
+
};
|
|
400
|
+
}
|
|
245
401
|
const found = await fetchItem(id, lang);
|
|
246
402
|
if (!found) {
|
|
247
403
|
return null;
|
|
@@ -249,6 +405,12 @@ export async function marketplaceWizard(id, lang) {
|
|
|
249
405
|
if (!readable(found.definition)) {
|
|
250
406
|
throw new ServiceError("refused", "Diese Vorlage braucht eine neuere Version der App. Bitte aktualisiere die App.");
|
|
251
407
|
}
|
|
408
|
+
// A wizard whose plugins are not here would stop at its first step that uses them.
|
|
409
|
+
const have = await pluginIdsOf(currentTenant());
|
|
410
|
+
const needs = pluginsOf(wizardSchema.parse(found.definition)).filter((p) => !have.has(p));
|
|
411
|
+
if (needs.length) {
|
|
412
|
+
throw new ServiceError("refused", `Diese Vorlage braucht ${needs.length === 1 ? "das Plugin" : "die Plugins"} ${needs.join(", ")}: mit Pro auf engenty.ai dabei.`);
|
|
413
|
+
}
|
|
252
414
|
return {
|
|
253
415
|
id: found.id,
|
|
254
416
|
revision: found.revision,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { formatsFor } from "@engenty-wizards/shared/definition";
|
|
1
|
+
import { formatsFor, optionsFromData, slotText, wizardLang, } from "@engenty-wizards/shared/definition";
|
|
2
2
|
import { and, count, desc, eq, gte, inArray, max, or, sql } from "drizzle-orm";
|
|
3
3
|
import { canSpend, MICROS_PER_CREDIT } from "../credits/credits.js";
|
|
4
4
|
import { db, schema } from "../db/client.js";
|
|
@@ -159,7 +159,31 @@ const CHAT_KINDS = new Set([
|
|
|
159
159
|
"color",
|
|
160
160
|
"items",
|
|
161
161
|
"location",
|
|
162
|
+
"slot",
|
|
162
163
|
]);
|
|
164
|
+
/** A field's choices in this run: what its `optionsFrom` finds in earlier steps, else the fixed ones. */
|
|
165
|
+
function choicesOf(run, field) {
|
|
166
|
+
const found = field.optionsFrom ? optionsFromData(field.optionsFrom, run.state.outputs) : [];
|
|
167
|
+
return found.length ? found : field.options;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* What a client needs besides the plain field: a slot's times as the person reads them, and the
|
|
171
|
+
* one value of them to send back.
|
|
172
|
+
*/
|
|
173
|
+
function slotHints(run, field, options) {
|
|
174
|
+
if (field.kind !== "slot") {
|
|
175
|
+
return {};
|
|
176
|
+
}
|
|
177
|
+
const lang = wizardLang(run.definition);
|
|
178
|
+
const value = run.state.values[field.id];
|
|
179
|
+
return {
|
|
180
|
+
times: (options ?? []).map((o) => ({ value: o, label: slotText(o, lang) })),
|
|
181
|
+
...(typeof value === "string" ? { valueText: slotText(value, lang) } : {}),
|
|
182
|
+
hint: options?.length
|
|
183
|
+
? "One appointment time: show the person the labels, answer with the value of the one they pick, exactly as given."
|
|
184
|
+
: "No times are free right now: tell the person.",
|
|
185
|
+
};
|
|
186
|
+
}
|
|
163
187
|
/** Where the person can go on in a browser: the run page of a live run, the studio for a test. */
|
|
164
188
|
/** The live run's page — the wizard itself, never the studio. A test run has none. */
|
|
165
189
|
async function browserUrl(run) {
|
|
@@ -197,20 +221,24 @@ function waitingFor(run, current) {
|
|
|
197
221
|
return {
|
|
198
222
|
page: current.id,
|
|
199
223
|
title: current.title,
|
|
200
|
-
fields: current.fields.map((f) =>
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
224
|
+
fields: current.fields.map((f) => {
|
|
225
|
+
const options = choicesOf(run, f);
|
|
226
|
+
return {
|
|
227
|
+
id: f.id,
|
|
228
|
+
label: f.label,
|
|
229
|
+
kind: f.kind,
|
|
230
|
+
required: Boolean(f.required),
|
|
231
|
+
options,
|
|
232
|
+
placeholder: f.placeholder,
|
|
233
|
+
help: f.help,
|
|
234
|
+
default: f.default,
|
|
235
|
+
value: run.state.values[f.id],
|
|
236
|
+
columns: f.columns,
|
|
237
|
+
// A file, a recording or a signature comes from the person's device: the run page.
|
|
238
|
+
inChat: CHAT_KINDS.has(f.kind),
|
|
239
|
+
...slotHints(run, f, options),
|
|
240
|
+
};
|
|
241
|
+
}),
|
|
214
242
|
};
|
|
215
243
|
}
|
|
216
244
|
if (current.type === "review") {
|
|
@@ -233,8 +233,10 @@ export async function createWizard(userId, input, writer = { source: "studio" })
|
|
|
233
233
|
await putLink(shareToken, "wizard", id);
|
|
234
234
|
if (fromStarter) {
|
|
235
235
|
await seedFiles(id, fromStarter.files);
|
|
236
|
-
// Counted at the marketplace, beside the request.
|
|
237
|
-
|
|
236
|
+
// Counted at the marketplace, beside the request; a plugin's starter is not the marketplace's.
|
|
237
|
+
if (!fromStarter.plugin) {
|
|
238
|
+
void countInstall(fromStarter.id);
|
|
239
|
+
}
|
|
238
240
|
}
|
|
239
241
|
if (input.note) {
|
|
240
242
|
await addMessage(id, { role: "assistant", content: input.note, changed: true }, writer);
|
|
@@ -21,7 +21,8 @@ function stepTool(plugin, tool, ctx) {
|
|
|
21
21
|
tenantId: ctx.tenantId,
|
|
22
22
|
space,
|
|
23
23
|
project: space,
|
|
24
|
-
wizard: { title: ctx.def.title },
|
|
24
|
+
wizard: { id: ctx.store.wizardId, title: ctx.def.title },
|
|
25
|
+
mode: ctx.test ? "test" : "live",
|
|
25
26
|
signal: ctx.signal,
|
|
26
27
|
emit: (message) => ctx.emit("tool", message),
|
|
27
28
|
})),
|
|
@@ -113,3 +114,30 @@ export async function assistantToolsOf(turn) {
|
|
|
113
114
|
}
|
|
114
115
|
return tools;
|
|
115
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* The admin talks to the space assistant from a plugin's own page: what the plugin says that page
|
|
119
|
+
* holds now, and its name. `null` when the tenant has no such plugin.
|
|
120
|
+
*/
|
|
121
|
+
export async function assistantPageOf(tenantId, pluginId, space) {
|
|
122
|
+
const plugin = (await pluginsOf(tenantId)).find((p) => p.source.id === pluginId);
|
|
123
|
+
if (!plugin) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const blocks = [];
|
|
127
|
+
for (const page of plugin.assistantPages) {
|
|
128
|
+
try {
|
|
129
|
+
const text = await page.block(space);
|
|
130
|
+
if (text?.trim()) {
|
|
131
|
+
blocks.push(text.trim().slice(0, MAX_BLOCK));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
console.error(`[plugins] ${pluginId}: the assistant's page block failed:`, err);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
name: plugin.source.manifest.name,
|
|
140
|
+
description: plugin.source.manifest.description ?? null,
|
|
141
|
+
blocks,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,n as t,t as n}from"./jsx-runtime-D3jfb0Ew.js";import{E as r,Z as i}from"./surface-BE-3Z1DP.js";import{D as a,G as o,H as s,c,f as l,g as u,h as d,j as f,k as p,n as ee,o as m,r as h,s as g,t as _,x as v}from"./ui-BZ01zr3i.js";import{n as y,r as b}from"./upload-U0i8fAW3.js";import{t as x}from"./external-link-BwCtn1nW.js";import{B as te,H as S,I as C,U as w,W as T,_t as E,at as D,ft as O}from"./index-DHM9S48l.js";import{n as k}from"./LocalRuntime-D7bzT40S.js";var A={name:`hard-drive`,size:24,node:[[`path`,{d:`M10 16h.01`,key:`1bzywj`}],[`path`,{d:`M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z`,key:`18tbho`}],[`path`,{d:`M21.946 12.013H2.054`,key:`zqlbp7`}],[`path`,{d:`M6 16h.01`,key:`1pmjb7`}]]};A.node;var j=o(A),M={name:`layout-grid`,size:24,node:[[`rect`,{width:`7`,height:`7`,x:`3`,y:`3`,rx:`1`,key:`1g98yp`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`3`,rx:`1`,key:`6d4xhi`}],[`rect`,{width:`7`,height:`7`,x:`14`,y:`14`,rx:`1`,key:`nxv5o0`}],[`rect`,{width:`7`,height:`7`,x:`3`,y:`14`,rx:`1`,key:`1bb6yr`}]]};M.node;var N=o(M),P={name:`list`,size:24,node:[[`path`,{d:`M3 5h.01`,key:`18ugdj`}],[`path`,{d:`M3 12h.01`,key:`nlz23k`}],[`path`,{d:`M3 19h.01`,key:`noohij`}],[`path`,{d:`M8 5h13`,key:`1pao27`}],[`path`,{d:`M8 12h13`,key:`1za7za`}],[`path`,{d:`M8 19h13`,key:`m83p4d`}]]};P.node;var F=o(P),I=e(t(),1),L=e=>[`project-files`,e];function R(e){return r({queryKey:L(e),queryFn:()=>v.get(`/api/studio/projects/${e}/files`),refetchInterval:e=>e.state.data?.files.some(e=>e.status===`pending`)?2e3:!1})}function z(e,t){return a(`/api/studio/projects/${e}/files/${t}/content`)}function B(e,t=!1){let n=i(),[r,a]=(0,I.useState)(!1),[o,s]=(0,I.useState)(null),c=()=>n.invalidateQueries({queryKey:L(e)}),l=async e=>{s(null);try{await e()}catch(e){s(e.message)}finally{await c()}};return{busy:r,error:o,readOnly:t,upload:async(t,n)=>{a(!0),await l(async()=>{for(let r of n)await v.upload(`/api/studio/projects/${e}/files?kind=${t}`,r),await c()}),a(!1)},describe:(t,n)=>l(()=>v.patch(`/api/studio/projects/${e}/files/${t}`,{description:n})),remove:t=>l(()=>v.del(`/api/studio/projects/${e}/files/${t}`)),reindex:t=>l(()=>v.post(`/api/studio/projects/${e}/files/${t}/reindex`)),order:(t,n)=>l(()=>v.put(`/api/studio/projects/${e}/files/order`,{kind:t,ids:n}))}}function V(e,t){let n=`wz.layout.${e}`,[r,i]=(0,I.useState)(()=>{try{let e=localStorage.getItem(n);return e===`list`||e===`cards`?e:t}catch{return t}});return[r,()=>i(e=>{let t=e===`list`?`cards`:`list`;try{localStorage.setItem(n,t)}catch{}return t})]}function H(e,t,n=700){let[r,i]=(0,I.useState)(`idle`),[a,o]=(0,I.useState)(null),s=JSON.stringify(e),c=(0,I.useRef)(s),l=(0,I.useRef)({value:e,json:s,save:t});l.current={value:e,json:s,save:t};let u=(0,I.useRef)(Promise.resolve()),d=(0,I.useCallback)(()=>{let e=l.current;e.json!==c.current&&(c.current=e.json,i(`saving`),u.current=u.current.then(async()=>{try{await e.save(e.value),o(null),i(`saved`)}catch(e){c.current=``,o(e.message),i(`error`)}}))},[]);return(0,I.useEffect)(()=>{if(s===c.current)return;let e=setTimeout(d,n);return()=>clearTimeout(e)},[s,n,d]),(0,I.useEffect)(()=>d,[d]),{state:r,error:a}}function U(e){return e<1e6?`${Math.max(1,Math.round(e/1e3))} KB`:`${(e/1e6).toFixed(1)} MB`}var W=e(n(),1);function G({id:e,children:t}){return(0,W.jsx)(`div`,{id:e,className:`scroll-mt-24 max-md:scroll-mt-36`,children:t})}function K({title:e,hint:t,save:n,action:r,locked:i,plain:a,children:o}){return(0,W.jsxs)(`section`,{className:`flex flex-col gap-2.5`,children:[(0,W.jsxs)(`div`,{className:`flex items-start justify-between gap-4 px-1`,children:[(0,W.jsxs)(`div`,{className:`min-w-0`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,W.jsx)(`h2`,{className:`font-display font-semibold text-lg leading-tight`,children:e}),n?.state===`saving`?(0,W.jsxs)(`span`,{className:`inline-flex items-center gap-1.5 text-[0.75rem] text-ink-3`,children:[(0,W.jsx)(l,{className:`size-3`}),` `,f(`project.saving`)]}):n?.state===`saved`?(0,W.jsxs)(`span`,{className:`inline-flex items-center gap-1 text-[0.75rem] text-moss`,children:[(0,W.jsx)(s,{className:`size-3.5`}),` `,f(`settings.saved`)]}):null]}),t?(0,W.jsx)(`p`,{className:`mt-1 text-[0.875rem] text-ink-3 leading-snug`,children:t}):null]}),r?(0,W.jsx)(`div`,{className:`shrink-0`,children:r}):null]}),a?o:(0,W.jsxs)(ee,{className:`p-3.5 sm:p-5`,children:[i?(0,W.jsx)(`fieldset`,{disabled:!0,className:`min-w-0`,children:o}):o,n?.state===`error`&&n.error?(0,W.jsx)(`p`,{className:`mt-4 text-[0.875rem] text-rose`,children:n.error}):null]})]})}function q({children:e,layout:t,onToggle:n}){return(0,W.jsxs)(`div`,{className:`mb-3 flex items-start gap-2`,children:[(0,W.jsx)(`div`,{className:`min-w-0 flex-1`,children:(0,W.jsx)(`div`,{className:`w-56 max-w-full transition-[width] duration-200 focus-within:w-full has-[input:not(:placeholder-shown)]:w-full`,children:e})}),(0,W.jsx)(m,{label:f(t===`list`?`project.viewCards`:`project.viewList`),onClick:n,children:t===`list`?(0,W.jsx)(N,{className:`size-4`}):(0,W.jsx)(F,{className:`size-4`})})]})}function J({value:e,onChange:t,onEnter:n,placeholder:r,busy:i}){return(0,W.jsxs)(`div`,{className:`relative`,children:[(0,W.jsx)(y,{className:`-translate-y-1/2 pointer-events-none absolute top-1/2 left-3 size-4 text-ink-4`}),(0,W.jsx)(`input`,{type:`search`,value:e,placeholder:r,onChange:e=>t(e.target.value),onKeyDown:e=>e.key===`Enter`&&n?.(),className:`h-9 w-full rounded-lg border border-input bg-card pr-3 pl-9 text-[0.875rem] text-ink outline-none transition placeholder:text-ink-4 focus:border-focus focus:ring-4 focus:ring-focus-glow`}),i?(0,W.jsx)(l,{className:`-translate-y-1/2 absolute top-1/2 right-3 size-4 text-ink-3`}):null]})}function Y({onFiles:e,accept:t,multiple:n=!0,className:r,children:i}){return(0,W.jsxs)(`label`,{onDragOver:e=>{e.preventDefault(),e.currentTarget.dataset.over=`1`},onDragLeave:e=>{delete e.currentTarget.dataset.over},onDrop:t=>{t.preventDefault(),delete t.currentTarget.dataset.over;let r=Array.from(t.dataTransfer.files);r.length&&e(n?r:r.slice(0,1))},className:u(`flex cursor-pointer items-center justify-center gap-2 rounded-lg border border-input border-dashed text-[0.875rem] text-ink-3 transition focus-within:border-focus focus-within:ring-4 focus-within:ring-focus-glow hover:border-ink-4 hover:text-ink data-[over]:border-focus data-[over]:bg-paper-2 data-[over]:text-ink`,r),children:[i,(0,W.jsx)(`input`,{className:`sr-only`,type:`file`,accept:t,multiple:n,onChange:t=>{let n=Array.from(t.target.files??[]);t.target.value=``,n.length&&e(n)}})]})}var X=`mt-1.5 text-[0.8125rem] text-ink-3`;function Z(e){let t=i(),[n,r]=(0,I.useState)(!1),a=E({mutationFn:e=>v.post(`/api/studio/account/link`,e),onSuccess:({url:e})=>{k(e),r(!0)}});return(0,I.useEffect)(()=>{if(!n)return;let e=setInterval(()=>void t.invalidateQueries({queryKey:[`me`]}),2e3),i=setTimeout(()=>r(!1),3e5);return()=>{clearInterval(e),clearTimeout(i)}},[n,t]),(0,I.useEffect)(()=>{e&&r(!1)},[e]),{link:a,waiting:n}}function Q({link:e,waiting:t}){return e.isError?(0,W.jsx)(`p`,{className:`text-[0.8125rem] text-rose`,children:f(`local.accountFailed`)}):t?(0,W.jsxs)(`p`,{className:`flex items-center gap-2 text-[0.8125rem] text-ink-3`,children:[(0,W.jsx)(l,{className:`size-3.5`}),` `,f(`local.accountWaiting`)]}):null}function ne(){let e=Z(!1),{link:t}=e,[n,r]=(0,I.useState)(``);return(0,W.jsxs)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:[(0,W.jsxs)(`div`,{className:`flex items-start gap-4 py-5 first:pt-0 last:pb-0`,children:[(0,W.jsx)(`div`,{className:`flex size-11 shrink-0 items-center justify-center rounded-full bg-paper-2 text-ink-2`,children:(0,W.jsx)(j,{className:`size-5`})}),(0,W.jsxs)(`div`,{className:`min-w-0`,children:[(0,W.jsx)(`div`,{className:`font-medium text-[0.9375rem]`,children:f(`account.local`)}),(0,W.jsx)(`p`,{className:`mt-1 text-[0.875rem] text-ink-3 leading-relaxed`,children:f(`account.localText`)})]})]}),w.account?(0,W.jsxs)(`div`,{className:`flex flex-col gap-4 py-5 last:pb-0`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`div`,{className:`font-medium text-[0.9375rem]`,children:f(`account.with`)}),(0,W.jsxs)(`ul`,{className:`mt-2 flex flex-col gap-2 text-[0.875rem] text-ink-2 leading-snug`,children:[(0,W.jsxs)(`li`,{className:`flex items-start gap-2.5`,children:[(0,W.jsx)(b,{className:`mt-0.5 size-4 shrink-0 text-amber`}),f(`account.withCredits`)]}),(0,W.jsxs)(`li`,{className:`flex items-start gap-2.5`,children:[(0,W.jsx)(O,{className:`mt-0.5 size-4 shrink-0 text-cobalt`}),f(`account.withCloud`)]})]})]}),(0,W.jsx)(`div`,{children:(0,W.jsx)(_,{busy:t.isPending&&!t.variables?.signup,onClick:()=>t.mutate({}),children:f(`account.signIn`)})})]}):null,w.account?(0,W.jsxs)(`form`,{className:`flex flex-col gap-3 py-5 last:pb-0`,onSubmit:e=>{e.preventDefault(),t.mutate({signup:!0,code:n.trim()||void 0})},children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`div`,{className:`font-medium text-[0.9375rem]`,children:f(`account.new`)}),(0,W.jsx)(`p`,{className:`mt-1 text-[0.875rem] text-ink-3 leading-relaxed`,children:f(`account.newHint`)})]}),(0,W.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,W.jsx)(g,{value:n,maxLength:64,autoComplete:`off`,spellCheck:!1,placeholder:f(`account.code`),"aria-label":f(`account.code`),onChange:e=>r(e.target.value),className:`w-56 font-mono text-[0.875rem]`}),(0,W.jsx)(_,{type:`submit`,variant:`secondary`,className:`h-11`,busy:t.isPending&&!!t.variables?.signup,children:f(`account.create`)})]}),(0,W.jsx)(Q,{...e})]}):null]})}var $={start:`account.kind.start`,monthly:`account.kind.monthly`,gift:`account.kind.gift`};function re({account:e}){let t=i(),n=Z(e.signedIn),r=E({mutationFn:()=>v.del(`/api/studio/account`),onSuccess:()=>t.invalidateQueries({queryKey:[`me`]})}),a=new Intl.DateTimeFormat(p,{dateStyle:`medium`});return(0,W.jsxs)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:[(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-4 gap-y-3 py-5 first:pt-0`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`truncate font-medium text-[0.9375rem]`,children:e.name||e.email}),e.signedIn?(0,W.jsx)(h,{tone:`live`,children:f(`account.linked`)}):null]}),(0,W.jsx)(`div`,{className:`truncate text-[0.875rem] text-ink-3`,children:e.email})]}),(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,W.jsxs)(_,{variant:`secondary`,onClick:()=>k(e.url),children:[f(`setup.openAccount`),` `,(0,W.jsx)(x,{className:`size-4`})]}),(0,W.jsxs)(_,{variant:`ghost`,busy:r.isPending,onClick:()=>r.mutate(),children:[(0,W.jsx)(D,{className:`size-4`}),` `,f(`nav.logout`)]})]})]}),e.signedIn?null:(0,W.jsxs)(`div`,{className:`flex flex-col gap-3 py-5`,children:[(0,W.jsx)(`p`,{className:`text-[0.875rem] text-ink-2`,children:f(`local.accountExpired`)}),(0,W.jsx)(`div`,{children:(0,W.jsx)(_,{busy:n.link.isPending,onClick:()=>n.link.mutate({}),children:f(`account.signInAgain`)})}),(0,W.jsx)(Q,{...n})]}),e.credits===null?null:(0,W.jsxs)(`div`,{className:`py-5`,children:[(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-4 gap-y-3`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsx)(`div`,{className:`text-[0.8125rem] text-ink-3`,children:f(`account.credits`)}),(0,W.jsx)(`div`,{className:`font-display font-semibold text-[1.375rem] tabular-nums leading-tight`,children:f(`nav.credits`,{n:Math.floor(e.credits).toLocaleString()})})]}),(0,W.jsxs)(_,{variant:`secondary`,onClick:()=>k(`${e.url}/billing`),children:[f(`account.topUp`),` `,(0,W.jsx)(x,{className:`size-4`})]})]}),e.expiring.length?(0,W.jsx)(`ul`,{className:`mt-3 flex flex-col gap-1 text-[0.8125rem] text-ink-3 tabular-nums`,children:e.expiring.map(e=>(0,W.jsxs)(`li`,{children:[f(`account.expires`,{n:Math.floor(e.credits).toLocaleString(),date:a.format(new Date(e.expiresAt))}),$[e.kind]?(0,W.jsxs)(`span`,{className:`text-ink-4`,children:[` · `,f($[e.kind])]}):null]},`${e.kind}:${e.expiresAt}`))}):null]}),(0,W.jsxs)(`div`,{className:`flex items-start gap-2.5 py-5 text-[0.875rem] text-ink-2 leading-snug last:pb-0`,children:[(0,W.jsx)(O,{className:`mt-0.5 size-4 shrink-0 text-cobalt`}),(0,W.jsx)(`p`,{children:f(`account.cloud`,{host:C(e.cloudUrl)})})]})]})}function ie({me:e,fromAccount:t}){let n=i(),[r,a]=(0,I.useState)(e.profile),o=e=>a(t=>({...t,...e})),s=H(r,async e=>{await v.put(`/api/studio/profile`,e),await n.invalidateQueries({queryKey:[`me`]})});return(0,W.jsx)(K,{title:f(`account.profile`),hint:f(`account.hint`),save:s,children:(0,W.jsxs)(`div`,{className:`flex flex-col gap-6 sm:flex-row sm:gap-8`,children:[(0,W.jsxs)(`div`,{className:`flex shrink-0 flex-col items-center gap-2 sm:w-32`,children:[(0,W.jsx)(`div`,{className:`flex size-20 items-center justify-center overflow-hidden rounded-full bg-ember-tint font-semibold text-[1.75rem] text-ember-strong ring-1 ring-border-soft`,children:e.user.image?(0,W.jsx)(`img`,{src:e.user.image,alt:``,className:`size-full object-cover`}):T(r.name)||`?`}),(0,W.jsx)(`p`,{className:`text-center text-[0.75rem] text-ink-3 leading-snug`,children:f(`account.initials`)})]}),(0,W.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-5`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.name`)}),(0,W.jsx)(g,{value:r.name,maxLength:80,disabled:t,onChange:e=>o({name:e.target.value})}),(0,W.jsx)(`p`,{className:X,children:f(t?`account.fromAccount`:`account.nameHint`)})]}),(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.about`)}),(0,W.jsx)(d,{minRows:3,maxLength:2e3,value:r.about,onChange:e=>o({about:e.target.value})}),(0,W.jsx)(`p`,{className:X,children:f(`account.aboutHint`)})]}),(0,W.jsxs)(`div`,{className:`grid gap-5 sm:grid-cols-2`,children:[(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.email`)}),(0,W.jsx)(g,{type:`email`,value:r.email,maxLength:200,disabled:t,onChange:e=>o({email:e.target.value})})]}),(0,W.jsxs)(`div`,{children:[(0,W.jsx)(c,{children:f(`account.phone`)}),(0,W.jsx)(g,{type:`tel`,value:r.phone,maxLength:40,onChange:e=>o({phone:e.target.value})})]})]})]})]})})}function ae({me:e}){let t=e.mode===`managed`,n=t||!!e.account;return(0,W.jsxs)(`div`,{className:`flex flex-col gap-9`,children:[(0,W.jsx)(K,{title:f(`account.connection`),hint:f(`account.connectionHint`),children:t?(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-4`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,W.jsx)(`span`,{className:`truncate font-medium text-[0.9375rem]`,children:e.user.name}),(0,W.jsx)(h,{tone:`live`,children:f(`account.linked`)})]}),(0,W.jsx)(`div`,{className:`truncate text-[0.875rem] text-ink-3`,children:e.user.email})]}),e.manageUrl?(0,W.jsxs)(_,{variant:`secondary`,onClick:()=>k(`${e.manageUrl}/account`),children:[f(`setup.openAccount`),` `,(0,W.jsx)(x,{className:`size-4`})]}):null]}):e.account?(0,W.jsx)(re,{account:e.account}):(0,W.jsx)(ne,{})}),(0,W.jsx)(ie,{me:e,fromAccount:n},n?`account`:`own`),(0,W.jsx)(K,{title:f(`account.look`),hint:f(`account.lookHint`),children:(0,W.jsxs)(`div`,{className:`flex flex-col divide-y divide-border-soft`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-4 pb-4`,children:[(0,W.jsx)(`span`,{className:`font-medium text-[0.875rem]`,children:f(`nav.language`)}),(0,W.jsx)(S,{tone:`surface`})]}),(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-4 pt-4`,children:[(0,W.jsx)(`span`,{className:`font-medium text-[0.875rem]`,children:f(`nav.theme`)}),(0,W.jsx)(te,{})]})]})})]})}export{Y as a,K as c,H as d,B as f,N as h,G as i,U as l,R as m,Q as n,q as o,V as p,Z as r,J as s,ae as t,z as u};
|
|
@@ -1 +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,f as a,g as o,i as s,
|
|
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,f as a,g as o,i as s,j as c,s as l}from"./ui-BZ01zr3i.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/,``):c(`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}async function _(e){if(e)try{let t=await fetch(`https://raw.githubusercontent.com/engenty/engenty-wizards/v${e}/apps/web/src/about/changelog.json`,{signal:AbortSignal.timeout(5e3)});if(t.ok)return await t.json()}catch{}return(await r(async()=>{let{default:e}=await import(`./changelog-C8wFW63z.js`);return{default:e}},[])).default}function v({open:e,onClose:t,version:n}){let[r,v]=(0,u.useState)(null),[y,b]=(0,u.useState)(``);(0,u.useEffect)(()=>{if(!e||r)return;let t=!1;return _(n).then(e=>{t||v(e)}),()=>{t=!0}},[e,r,n]),(0,u.useEffect)(()=>{e||b(``)},[e]);let x=r?g(r,y):[];return(0,d.jsxs)(s,{open:e,onClose:t,title:c(`about.changelog`),wide:!0,children:[(0,d.jsx)(`p`,{className:`-mt-3 mb-4 text-[0.875rem] text-ink-3`,children:c(`about.changelogHint`)}),r===null?(0,d.jsx)(`div`,{className:`flex justify-center py-10 text-ink-3`,children:(0,d.jsx)(a,{})}):r.length===0?(0,d.jsx)(i,{children:c(`about.changelogEmpty`)}):(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(l,{type:`search`,value:y,placeholder:c(`about.search`),onChange:e=>b(e.target.value)}),x.length===0?(0,d.jsx)(i,{children:c(`about.noMatches`)}):null,x.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-[1rem]`,children:[p(e),(0,d.jsx)(`span`,{className:`font-normal font-sans text-[0.8125rem] 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-[0.875rem]`,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-[0.75rem] 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-[0.75rem] text-rose`,children:c(`about.breaking`)}):null]})]},e.id)})})]},e.version??`unreleased`))]})]})}export{v as ChangelogDialog};
|
|
@@ -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,f as a,i as o,j as s,k as c,s as l}from"./ui-BZ01zr3i.js";import{t as u}from"./external-link-BwCtn1nW.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:i}){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-[0.875rem] text-ink underline-offset-4 hover:underline`,children:[e,(0,m.jsx)(u,{"aria-hidden":!0,className:`size-3 text-ink-4`})]}):(0,m.jsx)(`span`,{className:`font-medium text-[0.875rem] text-ink`,children:e}),n?(0,m.jsx)(`span`,{className:`text-[0.75rem] text-ink-3 tabular-nums`,children:n}):null,(0,m.jsx)(`span`,{className:`text-[0.75rem] text-ink-3`,children:r})]}),i?(0,m.jsx)(`p`,{className:`mt-0.5 text-[0.8125rem] text-ink-3`,children:i}):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-[1rem]`,children:e}),t?(0,m.jsx)(`p`,{className:`mt-2 text-[0.8125rem] 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[c]},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-[0.75rem] 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,c]=(0,d.useState)(null),[u,g]=(0,d.useState)(``);(0,d.useEffect)(()=>{if(!e||n)return;let t=!1;return r(()=>import(`./oss-credits-CIxnNZor.js`).then(e=>{t||c(e.default)}),[]),()=>{t=!0}},[e,n]),(0,d.useEffect)(()=>{e||g(``)},[e]);let b=u.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:s(`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)(o,{open:e,onClose:t,title:s(`about.credits`),wide:!0,children:[(0,m.jsx)(`p`,{className:`-mt-3 mb-4 text-[0.875rem] text-ink-3`,children:s(`about.creditsHint`)}),(0,m.jsx)(l,{type:`search`,value:u,placeholder:s(`about.search`),onChange:e=>g(e.target.value)}),C.length>0?(0,m.jsx)(_,{title:s(`about.creditsProduct`),children:(0,m.jsx)(v,{credits:C})}):null,w.length>0?(0,m.jsx)(_,{title:s(`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)(a,{})}):T.length>0?(0,m.jsx)(_,{title:s(`about.creditsDeps`),hint:b?void 0:s(`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)(i,{children:s(`about.noMatches`)}):null]})}export{b as CreditsDialog};
|