wizards 0.5.7 → 0.5.9
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/architect.js +13 -26
- package/apps/runtime/dist/agents/studio-assistant.js +19 -22
- package/apps/runtime/dist/agents/subscription.js +10 -9
- package/apps/runtime/dist/app.js +6 -6
- package/apps/runtime/dist/assistant/knows.js +10 -9
- package/apps/runtime/dist/connectors/external.js +3 -3
- package/apps/runtime/dist/connectors/index.js +23 -23
- package/apps/runtime/dist/connectors/via-account.js +6 -6
- package/apps/runtime/dist/documents/parse.js +3 -3
- package/apps/runtime/dist/engine/input.js +11 -11
- package/apps/runtime/dist/engine/requirements.js +7 -8
- package/apps/runtime/dist/engine/runner.js +10 -14
- package/apps/runtime/dist/engine/steps.js +6 -6
- package/apps/runtime/dist/engine/surface.js +2 -2
- package/apps/runtime/dist/film/step.js +5 -5
- package/apps/runtime/dist/harness/apple.js +2 -1
- package/apps/runtime/dist/harness/claude.js +2 -2
- package/apps/runtime/dist/harness/codex.js +2 -2
- package/apps/runtime/dist/harness/model.js +4 -5
- package/apps/runtime/dist/harness/terminal.js +4 -4
- package/apps/runtime/dist/media/conversation.js +18 -35
- package/apps/runtime/dist/media/transcribe.js +2 -1
- package/apps/runtime/dist/model-errors.js +1 -1
- package/apps/runtime/dist/models.js +32 -40
- package/apps/runtime/dist/plugins/runs.js +3 -5
- package/apps/runtime/dist/routes/api.js +9 -9
- package/apps/runtime/dist/routes/lang.js +14 -9
- package/apps/runtime/dist/routes/runs.js +5 -5
- package/apps/runtime/dist/routes/studio.js +38 -37
- package/apps/runtime/dist/services/access.js +4 -4
- package/apps/runtime/dist/services/architect.js +3 -12
- package/apps/runtime/dist/services/assistant-chats.js +2 -2
- package/apps/runtime/dist/services/brand.js +3 -3
- package/apps/runtime/dist/services/cloud.js +5 -5
- package/apps/runtime/dist/services/errors.js +2 -2
- package/apps/runtime/dist/services/knowledge-model.js +3 -3
- package/apps/runtime/dist/services/marketplace.js +3 -3
- package/apps/runtime/dist/services/package-file.js +9 -11
- package/apps/runtime/dist/services/package.js +8 -9
- package/apps/runtime/dist/services/profile.js +2 -1
- package/apps/runtime/dist/services/project-files.js +13 -13
- package/apps/runtime/dist/services/projects.js +7 -11
- package/apps/runtime/dist/services/runners.js +4 -4
- package/apps/runtime/dist/services/runs.js +7 -10
- package/apps/runtime/dist/services/shares.js +2 -2
- package/apps/runtime/dist/services/site.js +8 -11
- package/apps/runtime/dist/services/space-categories.js +7 -7
- package/apps/runtime/dist/services/space-data.js +20 -20
- package/apps/runtime/dist/services/spaces.js +7 -9
- package/apps/runtime/dist/services/wizards.js +11 -13
- package/apps/runtime/dist/store/index.js +2 -2
- package/apps/runtime/dist/texts.js +195 -0
- package/apps/runtime/dist/tools/plugin.js +7 -3
- package/apps/runtime/dist/widgets/step.js +2 -2
- package/apps/web/dist/assets/AboutDialog-CpI-cGpz.js +1 -0
- package/apps/web/dist/assets/{ChangelogDialog-rAtYZjxz.js → ChangelogDialog-BW56Y5UR.js} +1 -1
- package/apps/web/dist/assets/ChatView-CH8U-tRy.js +10 -0
- package/apps/web/dist/assets/EditorPage-Be5J_y4F.js +3 -0
- package/apps/web/dist/assets/{FlowPreview--3-yI51e.js → FlowPreview-CzmH4JUQ.js} +1 -1
- package/apps/web/dist/assets/{Harness-B9tvFe0U.js → Harness-CJKWO3AK.js} +2 -2
- package/apps/web/dist/assets/{NewWizardChannels-BxrBhC9U.js → NewWizardChannels-Ca2niMTY.js} +1 -1
- package/apps/web/dist/assets/NewWizardPage-D5gi4TYE.js +7 -0
- package/apps/web/dist/assets/{OnboardingPage-DPdH9sSj.js → OnboardingPage-Bm-c-D21.js} +1 -1
- package/apps/web/dist/assets/ProjectPage-C8nJCBZP.js +1 -0
- package/apps/web/dist/assets/{PublicRunner-Bv3TMKw4.js → PublicRunner-anxg3Rxz.js} +1 -1
- package/apps/web/dist/assets/{ReadOnly-CmqIrOAR.js → ReadOnly-i-6WBMSE.js} +1 -1
- package/apps/web/dist/assets/RunDrawer-4yvfW_2c.js +4 -0
- package/apps/web/dist/assets/{RunnerView-Cd1VAlIA.js → RunnerView-BkWQBa_M.js} +1 -1
- package/apps/web/dist/assets/SettingsPage-NL8r9S6R.js +1 -0
- package/apps/web/dist/assets/SetupPage-Crcfx4-p.js +1 -0
- package/apps/web/dist/assets/{SharePage-BT80wI1I.js → SharePage-CDEAtmBC.js} +1 -1
- package/apps/web/dist/assets/changelog-BGBuldNF.js +1 -0
- package/apps/web/dist/assets/{esm-BTVd6EFo.js → esm-BF1nonbH.js} +1 -1
- package/apps/web/dist/assets/index-C74LSJ-W.js +14 -0
- package/apps/web/dist/assets/{lock-ByHFI96G.js → lock-DVvM6IsA.js} +1 -1
- package/apps/web/dist/assets/{phone-KPwxAM1R.js → phone-3fG1okFs.js} +1 -1
- package/apps/web/dist/assets/{settings-menu-K5bg3QE3.js → settings-menu-D9fbi1Z0.js} +1 -1
- package/apps/web/dist/assets/ui-EuR3jezP.js +134 -0
- package/apps/web/dist/assets/{upload-BsIL8tNR.js → upload-BsMUhEfX.js} +1 -1
- package/apps/web/dist/index.html +2 -2
- package/apps/web/dist/mcp/flow.html +77 -77
- package/bin/wizards.mjs +15 -2
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +26 -9
- package/node_modules/@engenty-wizards/shared/dist/definition.js +125 -3
- package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.d.ts +1 -1
- package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.js +9 -8
- package/node_modules/@engenty-wizards/shared/dist/marketplace-search.js +6 -6
- package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +78 -205
- package/node_modules/@engenty-wizards/shared/dist/marketplace.js +167 -68
- package/node_modules/@engenty-wizards/shared/dist/projects.d.ts +3 -6
- package/node_modules/@engenty-wizards/shared/dist/projects.js +9 -9
- package/node_modules/@engenty-wizards/shared/dist/providers.d.ts +33 -7
- package/node_modules/@engenty-wizards/shared/dist/providers.js +88 -37
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +298 -365
- package/node_modules/@engenty-wizards/shared/dist/run.js +582 -240
- package/node_modules/@engenty-wizards/shared/dist/texts.d.ts +36 -0
- package/node_modules/@engenty-wizards/shared/dist/texts.js +46 -0
- package/package.json +5 -1
- package/apps/web/dist/assets/AboutDialog-t9bayaIs.js +0 -1
- package/apps/web/dist/assets/ChatView-C3VqLT98.js +0 -10
- package/apps/web/dist/assets/EditorPage-D3Ef24b9.js +0 -3
- package/apps/web/dist/assets/NewWizardPage-C1_hsQPr.js +0 -7
- package/apps/web/dist/assets/ProjectPage-P40R1cPE.js +0 -1
- package/apps/web/dist/assets/RunDrawer-9qG1G-OY.js +0 -4
- package/apps/web/dist/assets/SettingsPage-DFz4UMfo.js +0 -1
- package/apps/web/dist/assets/SetupPage-B0UBNMB9.js +0 -1
- package/apps/web/dist/assets/changelog-BpSBMjpm.js +0 -1
- package/apps/web/dist/assets/index-D8vwgldH.js +0 -14
- package/apps/web/dist/assets/ui-4bQx9I1f.js +0 -134
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { dayOf, slugOf } from "@engenty-wizards/shared/knowledge";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { columnIdOf } from "@engenty-wizards/shared/space-data";
|
|
4
4
|
import { generateText, Output } from "ai";
|
|
5
5
|
import { and, eq, inArray, isNull } from "drizzle-orm";
|
|
@@ -504,12 +504,12 @@ export async function writeSummary(valueId) {
|
|
|
504
504
|
where: eq(schema.spaceCategoryValue.id, valueId),
|
|
505
505
|
});
|
|
506
506
|
if (!value) {
|
|
507
|
-
throw new ServiceError("not_found",
|
|
507
|
+
throw new ServiceError("not_found", note("valueNotExist"));
|
|
508
508
|
}
|
|
509
509
|
const category = await categoryRow(value.categoryId);
|
|
510
510
|
const { items, total } = await itemsOfValue(value.id);
|
|
511
511
|
if (!items.length) {
|
|
512
|
-
throw new ServiceError("invalid",
|
|
512
|
+
throw new ServiceError("invalid", note("nothingFiledUnderValue"));
|
|
513
513
|
}
|
|
514
514
|
const model = await textModel("standard");
|
|
515
515
|
const result = await generateText({
|
|
@@ -4,7 +4,7 @@ import { DEFINITION_VERSION, readable, wizardSchema, } from "@engenty-wizards/sh
|
|
|
4
4
|
import { capabilitiesOf, costTierOf, effortOf, formatsOf, MARKETPLACE_LANGS, pluginsOf, } from "@engenty-wizards/shared/marketplace";
|
|
5
5
|
import { wizardOutline } from "@engenty-wizards/shared/marketplace-entry";
|
|
6
6
|
import { searchEntries } from "@engenty-wizards/shared/marketplace-search";
|
|
7
|
-
import {
|
|
7
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
8
8
|
import { and, eq, inArray, notInArray } from "drizzle-orm";
|
|
9
9
|
import { formulaEstimate } from "../credits/estimate.js";
|
|
10
10
|
import { control, controlDb, db, schema, withTenant } from "../db/client.js";
|
|
@@ -414,13 +414,13 @@ export async function marketplaceWizard(id, lang) {
|
|
|
414
414
|
return null;
|
|
415
415
|
}
|
|
416
416
|
if (!readable(found.definition)) {
|
|
417
|
-
throw new ServiceError("refused",
|
|
417
|
+
throw new ServiceError("refused", note("templateNeedsNewerVersion"));
|
|
418
418
|
}
|
|
419
419
|
// A wizard whose plugins are not here would stop at its first step that uses them.
|
|
420
420
|
const have = await pluginIdsOf(currentTenant());
|
|
421
421
|
const needs = pluginsOf(wizardSchema.parse(found.definition)).filter((p) => !have.has(p));
|
|
422
422
|
if (needs.length) {
|
|
423
|
-
throw new ServiceError("refused",
|
|
423
|
+
throw new ServiceError("refused", note("templateNeedsPlugins", { count: needs.length, plugins: needs }));
|
|
424
424
|
}
|
|
425
425
|
return {
|
|
426
426
|
id: found.id,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
2
2
|
import { manifestSchema, PACKAGE_FILES, PACKAGE_FORMAT, PACKAGE_MANIFEST, PACKAGE_MAX_BYTES, } from "@engenty-wizards/shared/wizard-package";
|
|
3
3
|
import { cleanPath, WORKSPACE_LIMITS } from "@engenty-wizards/shared/workspace";
|
|
4
4
|
import { strFromU8, unzipSync } from "fflate";
|
|
@@ -13,7 +13,7 @@ export function json(data) {
|
|
|
13
13
|
return JSON.parse(strFromU8(data));
|
|
14
14
|
}
|
|
15
15
|
catch {
|
|
16
|
-
throw invalid(
|
|
16
|
+
throw invalid(note("wizardJsonUnreadable"));
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
/** A manifest, or a bare definition: a wizard without workspace is fully told by its JSON. */
|
|
@@ -23,7 +23,7 @@ export function readManifest(raw) {
|
|
|
23
23
|
}
|
|
24
24
|
const parsed = manifestSchema.safeParse(raw);
|
|
25
25
|
if (!parsed.success) {
|
|
26
|
-
throw invalid(
|
|
26
|
+
throw invalid(note("wizardFileComesNewer"));
|
|
27
27
|
}
|
|
28
28
|
return parsed.data;
|
|
29
29
|
}
|
|
@@ -46,26 +46,24 @@ export function readPackage(data) {
|
|
|
46
46
|
total += file.originalSize;
|
|
47
47
|
count += 1;
|
|
48
48
|
if (file.originalSize > WORKSPACE_LIMITS.fileBytes) {
|
|
49
|
-
throw invalid(
|
|
49
|
+
throw invalid(note("fileOver5Mb", { name: file.name }));
|
|
50
50
|
}
|
|
51
51
|
if (count > WORKSPACE_LIMITS.files + 1 || total > PACKAGE_MAX_BYTES) {
|
|
52
|
-
throw invalid(
|
|
52
|
+
throw invalid(note("wizardFileTooLarge"));
|
|
53
53
|
}
|
|
54
54
|
return true;
|
|
55
55
|
},
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
catch (err) {
|
|
59
|
-
throw err instanceof ServiceError
|
|
60
|
-
? err
|
|
61
|
-
: invalid(bilingual("Die Wizard-Datei lässt sich nicht öffnen. Exportiere den Wizard neu und versuche es noch einmal.", "The wizard file can’t be opened. Export the wizard again and try once more."));
|
|
59
|
+
throw err instanceof ServiceError ? err : invalid(note("wizardFileNotOpened"));
|
|
62
60
|
}
|
|
63
61
|
// A package unpacked and zipped again often sits in a folder of its own.
|
|
64
62
|
const manifestPath = Object.keys(entries)
|
|
65
63
|
.filter((name) => name === PACKAGE_MANIFEST || name.endsWith(`/${PACKAGE_MANIFEST}`))
|
|
66
64
|
.sort((a, b) => a.length - b.length)[0];
|
|
67
65
|
if (manifestPath === undefined) {
|
|
68
|
-
throw invalid(
|
|
66
|
+
throw invalid(note("wizardJsonMissing"));
|
|
69
67
|
}
|
|
70
68
|
const root = manifestPath.slice(0, -PACKAGE_MANIFEST.length);
|
|
71
69
|
const files = Object.entries(entries)
|
|
@@ -73,12 +71,12 @@ export function readPackage(data) {
|
|
|
73
71
|
.map(([name, content]) => {
|
|
74
72
|
const path = cleanPath(name.slice(root.length + PACKAGE_FILES.length));
|
|
75
73
|
if (!path) {
|
|
76
|
-
throw invalid(
|
|
74
|
+
throw invalid(note("notValidFilePath", { name }));
|
|
77
75
|
}
|
|
78
76
|
return { path, data: content };
|
|
79
77
|
});
|
|
80
78
|
if (files.reduce((n, f) => n + f.data.byteLength, 0) > WORKSPACE_LIMITS.totalBytes) {
|
|
81
|
-
throw invalid(
|
|
79
|
+
throw invalid(note("workspaceWizardFileLarger"));
|
|
82
80
|
}
|
|
83
81
|
return { manifest: readManifest(json(entries[manifestPath])), files };
|
|
84
82
|
}
|
|
@@ -4,6 +4,7 @@ import { strToU8, zipSync } from "fflate";
|
|
|
4
4
|
import { listConnectors } from "../connectors/external.js";
|
|
5
5
|
import { db, schema } from "../db/client.js";
|
|
6
6
|
import { getBlob } from "../files/blobs.js";
|
|
7
|
+
import { serverText } from "../texts.js";
|
|
7
8
|
import { requireAdmin } from "./access.js";
|
|
8
9
|
import { draftFiles, writeFile } from "./files.js";
|
|
9
10
|
import { pageTree } from "./knowledge.js";
|
|
@@ -144,16 +145,14 @@ lang = "en") {
|
|
|
144
145
|
// The shape is checked before anything is written; a wrong one leaves no wizard behind.
|
|
145
146
|
const { draft } = parseDraft(manifest.definition, files.map((f) => f.path));
|
|
146
147
|
const lacks = await missing(userId, projectId, draft, manifest);
|
|
147
|
-
const
|
|
148
|
+
const counts = {
|
|
149
|
+
name,
|
|
150
|
+
steps: serverText(lang, "stepCount", { count: draft.steps.length }),
|
|
151
|
+
files: serverText(lang, "fileCount", { count: files.length }),
|
|
152
|
+
};
|
|
148
153
|
const note = [
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
: `Imported${name ? ` from “${name}”` : ""}: ${draft.steps.length} steps, ${files.length} ${files.length === 1 ? "file" : "files"}.`,
|
|
152
|
-
lacks.length
|
|
153
|
-
? de
|
|
154
|
-
? `Diesem Space fehlt noch: ${lacks.join(", ")}. Füge es unter Einstellungen → Connectors hinzu.`
|
|
155
|
-
: `This space still needs: ${lacks.join(", ")}. Add it under Settings → Connectors.`
|
|
156
|
-
: "",
|
|
154
|
+
serverText(lang, name ? "importedFrom" : "imported", counts),
|
|
155
|
+
lacks.length ? serverText(lang, "spaceStillNeeds", { needs: lacks }) : "",
|
|
157
156
|
]
|
|
158
157
|
.filter(Boolean)
|
|
159
158
|
.join("\n\n");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isLang } from "@engenty-wizards/shared/definition";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
import { linkedAccount } from "../auth/account.js";
|
|
3
4
|
import { managed } from "../manage.js";
|
|
@@ -34,7 +35,7 @@ const langKey = (user) => `lang:${user.tenantId}:${user.id}`;
|
|
|
34
35
|
*/
|
|
35
36
|
export async function userLang(user) {
|
|
36
37
|
const lang = await readSetting(langKey(user));
|
|
37
|
-
return lang
|
|
38
|
+
return isLang(lang) ? lang : null;
|
|
38
39
|
}
|
|
39
40
|
export async function saveUserLang(user, lang) {
|
|
40
41
|
await writeSetting(langKey(user), lang);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PROJECT_LIMITS, projectFileLimit, } from "@engenty-wizards/shared/projects";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { generateText } from "ai";
|
|
4
4
|
import { and, asc, count, eq, max } from "drizzle-orm";
|
|
5
5
|
import { db, schema } from "../db/client.js";
|
|
@@ -79,14 +79,14 @@ export async function addProjectFile(projectId, input) {
|
|
|
79
79
|
const mime = documentMime(input.name, input.mime) || "application/octet-stream";
|
|
80
80
|
if (!accepts(input.kind, mime)) {
|
|
81
81
|
throw new ServiceError("invalid", input.kind === "logo"
|
|
82
|
-
?
|
|
82
|
+
? note("logoImagePngSvg")
|
|
83
83
|
: input.kind === "pattern"
|
|
84
|
-
?
|
|
85
|
-
:
|
|
84
|
+
? note("patternImageSvgPng")
|
|
85
|
+
: note("filesGoHere"));
|
|
86
86
|
}
|
|
87
87
|
const limit = projectFileLimit(input.kind, mime);
|
|
88
88
|
if (!input.data.byteLength || input.data.byteLength > limit) {
|
|
89
|
-
throw new ServiceError("invalid",
|
|
89
|
+
throw new ServiceError("invalid", note("chooseFileUpTo", { mb: Math.round(limit / 1_000_000) }));
|
|
90
90
|
}
|
|
91
91
|
const scope = and(eq(schema.projectFile.projectId, projectId), eq(schema.projectFile.kind, input.kind));
|
|
92
92
|
const [{ n, last }] = await db
|
|
@@ -94,7 +94,7 @@ export async function addProjectFile(projectId, input) {
|
|
|
94
94
|
.from(schema.projectFile)
|
|
95
95
|
.where(scope);
|
|
96
96
|
if (n >= PROJECT_LIMITS.files[input.kind]) {
|
|
97
|
-
throw new ServiceError("refused",
|
|
97
|
+
throw new ServiceError("refused", note("roomMostFiles", { count: PROJECT_LIMITS.files[input.kind] }));
|
|
98
98
|
}
|
|
99
99
|
const name = input.name.slice(0, 120) || "datei";
|
|
100
100
|
const ref = await saveAsset({
|
|
@@ -150,21 +150,21 @@ export async function addProjectFileFromUrl(projectId, input) {
|
|
|
150
150
|
headers: { "user-agent": "Mozilla/5.0 (compatible; engenty-wizards/0.1)" },
|
|
151
151
|
signal: AbortSignal.any([AbortSignal.timeout(60_000), ...(signal ? [signal] : [])]),
|
|
152
152
|
}).catch(() => {
|
|
153
|
-
throw new ServiceError("invalid",
|
|
153
|
+
throw new ServiceError("invalid", note("addressNotReached"));
|
|
154
154
|
});
|
|
155
155
|
if (!res.ok) {
|
|
156
|
-
throw new ServiceError("invalid",
|
|
156
|
+
throw new ServiceError("invalid", note("addressResponded", { status: res.status }));
|
|
157
157
|
}
|
|
158
158
|
const mime = (res.headers.get("content-type") ?? "").split(";")[0].trim().toLowerCase();
|
|
159
159
|
if (mime === "text/html" && kind !== "document") {
|
|
160
160
|
await res.body?.cancel();
|
|
161
|
-
throw new ServiceError("invalid",
|
|
161
|
+
throw new ServiceError("invalid", note("addressLeadsWebPage"), {
|
|
162
162
|
reason: "page",
|
|
163
163
|
url: res.url,
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
166
|
if (Number(res.headers.get("content-length") ?? 0) > projectFileLimit(kind, mime)) {
|
|
167
|
-
throw new ServiceError("invalid",
|
|
167
|
+
throw new ServiceError("invalid", note("addressFileTooLarge"));
|
|
168
168
|
}
|
|
169
169
|
const data = new Uint8Array(await res.arrayBuffer());
|
|
170
170
|
const name = decodeURIComponent(new URL(res.url).pathname.split("/").pop() || kind);
|
|
@@ -305,7 +305,7 @@ export async function reindexProjectFile(projectId, fileId) {
|
|
|
305
305
|
await requireWritableProject(projectId);
|
|
306
306
|
const row = await projectFile(projectId, fileId);
|
|
307
307
|
if (row.kind !== "document") {
|
|
308
|
-
throw new ServiceError("invalid",
|
|
308
|
+
throw new ServiceError("invalid", note("onlyDocumentsIndex"));
|
|
309
309
|
}
|
|
310
310
|
const [pending] = await db
|
|
311
311
|
.update(schema.projectFile)
|
|
@@ -380,7 +380,7 @@ export async function putOriginFile(origin, input) {
|
|
|
380
380
|
});
|
|
381
381
|
const mime = documentMime(input.name, input.mime) || "application/octet-stream";
|
|
382
382
|
if (!input.data.byteLength || input.data.byteLength > projectFileLimit("document", mime)) {
|
|
383
|
-
throw new ServiceError("invalid",
|
|
383
|
+
throw new ServiceError("invalid", note("emptyTooLargeDocument", { name: input.name }));
|
|
384
384
|
}
|
|
385
385
|
const name = input.name.slice(0, 120) || "datei";
|
|
386
386
|
const values = {
|
|
@@ -407,7 +407,7 @@ export async function putOriginFile(origin, input) {
|
|
|
407
407
|
.from(schema.projectFile)
|
|
408
408
|
.where(and(eq(schema.projectFile.projectId, input.space), eq(schema.projectFile.kind, "document")));
|
|
409
409
|
if (n >= PROJECT_LIMITS.files.document) {
|
|
410
|
-
throw new ServiceError("refused",
|
|
410
|
+
throw new ServiceError("refused", note("spaceMostDocuments", { count: PROJECT_LIMITS.files.document }));
|
|
411
411
|
}
|
|
412
412
|
const ref = await saveAsset({ kind: "project", mime, name, data: input.data });
|
|
413
413
|
id = ref.id;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { COLOR_SECTION_KINDS, cleanAssetSections, cleanLogoSections, FACT_TYPES, FONT_USES, FONT_WEIGHTS, GRADIENT_TYPES, orderColors, PROJECT_LIMITS, RULE_MARKS, } from "@engenty-wizards/shared/projects";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { and, count, eq, isNull } from "drizzle-orm";
|
|
4
4
|
import { nanoid } from "nanoid";
|
|
5
5
|
import { z } from "zod";
|
|
@@ -8,6 +8,7 @@ import { env } from "../env.js";
|
|
|
8
8
|
import { managed, tenantInfo } from "../manage.js";
|
|
9
9
|
import { spaceChanged } from "../plugins/events.js";
|
|
10
10
|
import { currentTenant } from "../tenants/tenant.js";
|
|
11
|
+
import { serverText } from "../texts.js";
|
|
11
12
|
import { mayBuild, requireAdmin, requireBuild, requireWritable } from "./access.js";
|
|
12
13
|
import { notFound, ServiceError } from "./errors.js";
|
|
13
14
|
import { forgetWizardLinks } from "./links.js";
|
|
@@ -148,10 +149,7 @@ const madeHere = () => and(eq(schema.project.tenantId, currentTenant()), isNull(
|
|
|
148
149
|
/** The tenant's projects a local install synced. */
|
|
149
150
|
const synced = () => and(eq(schema.project.tenantId, currentTenant()), eq(schema.project.origin, "local"));
|
|
150
151
|
/** What the first space is called, in the language of whoever first opens the studio. */
|
|
151
|
-
const FIRST_SPACE = {
|
|
152
|
-
cloud: { de: "Meine Wizards", en: "My wizards" },
|
|
153
|
-
local: { de: "Mein Computer", en: "My computer" },
|
|
154
|
-
};
|
|
152
|
+
const FIRST_SPACE = { cloud: "firstSpaceCloud", local: "firstSpaceLocal" };
|
|
155
153
|
/**
|
|
156
154
|
* A tenant that builds here always has a project of its own: the first one is made when its
|
|
157
155
|
* studio is first opened, named in that request's language.
|
|
@@ -163,7 +161,7 @@ async function ensureProject(lang = "en") {
|
|
|
163
161
|
await db.insert(schema.project).values({
|
|
164
162
|
id,
|
|
165
163
|
tenantId: currentTenant(),
|
|
166
|
-
name: FIRST_SPACE[env.manage.url ? "cloud" : "local"]
|
|
164
|
+
name: serverText(lang, FIRST_SPACE[env.manage.url ? "cloud" : "local"]),
|
|
167
165
|
});
|
|
168
166
|
spaceChanged("space.created", id);
|
|
169
167
|
}
|
|
@@ -230,9 +228,7 @@ export async function createProject(_userId, name) {
|
|
|
230
228
|
.where(eq(schema.project.tenantId, currentTenant()));
|
|
231
229
|
const limit = await projectLimit();
|
|
232
230
|
if (n >= limit) {
|
|
233
|
-
throw new ServiceError("refused", limit === 1
|
|
234
|
-
? bilingual("Hier ist nur ein Space möglich.", "Only one space is allowed here.")
|
|
235
|
-
: bilingual(`Hier sind höchstens ${limit} Spaces möglich.`, `You can have at most ${limit} spaces here.`));
|
|
231
|
+
throw new ServiceError("refused", limit === 1 ? note("onlyOneSpaceAllowed") : note("mostSpaces", { count: limit }));
|
|
236
232
|
}
|
|
237
233
|
const id = nanoid(12);
|
|
238
234
|
await db
|
|
@@ -256,7 +252,7 @@ export async function updateProject(userId, projectId, patch) {
|
|
|
256
252
|
return { ...s, headers };
|
|
257
253
|
});
|
|
258
254
|
if (patch.facts && new Set(patch.facts.map((f) => f.key)).size !== patch.facts.length) {
|
|
259
|
-
throw new ServiceError("invalid",
|
|
255
|
+
throw new ServiceError("invalid", note("twoEntriesSameKey"));
|
|
260
256
|
}
|
|
261
257
|
await db
|
|
262
258
|
.update(schema.project)
|
|
@@ -370,7 +366,7 @@ export async function deleteProject(userId, projectId) {
|
|
|
370
366
|
await requireAdmin();
|
|
371
367
|
const all = await db.query.project.findMany({ where: madeHere() });
|
|
372
368
|
if (all.length <= 1) {
|
|
373
|
-
throw new ServiceError("refused",
|
|
369
|
+
throw new ServiceError("refused", note("notDeleteLastSpace"));
|
|
374
370
|
}
|
|
375
371
|
await removeProject(projectId);
|
|
376
372
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { wizardLang } from "@engenty-wizards/shared/definition";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { BUILT_IN_RUNNERS, CONVERSATION_RUNNERS, DEFAULT_RUNNER, DEFAULT_RUNNER_SETTINGS, runnerFit, } from "@engenty-wizards/shared/runners";
|
|
4
4
|
import { env } from "../env.js";
|
|
5
5
|
import { conversationAccess, conversationAvailable } from "../models.js";
|
|
@@ -72,14 +72,14 @@ export async function checkRunnerSettings(settings) {
|
|
|
72
72
|
const ids = new Set(available.map((r) => r.id));
|
|
73
73
|
const unknown = settings.enabled.find((id) => !ids.has(id));
|
|
74
74
|
if (unknown) {
|
|
75
|
-
throw new ServiceError("invalid",
|
|
75
|
+
throw new ServiceError("invalid", note("unknownRunner", { unknown }));
|
|
76
76
|
}
|
|
77
77
|
const enabled = [...new Set(settings.enabled)];
|
|
78
78
|
if (!enabled.length) {
|
|
79
|
-
throw new ServiceError("invalid",
|
|
79
|
+
throw new ServiceError("invalid", note("leastOneRunnerStay"));
|
|
80
80
|
}
|
|
81
81
|
if (!enabled.includes(settings.default)) {
|
|
82
|
-
throw new ServiceError("invalid",
|
|
82
|
+
throw new ServiceError("invalid", note("linkOpenRunnerTurned"));
|
|
83
83
|
}
|
|
84
84
|
return { default: settings.default, enabled };
|
|
85
85
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FIELD_WAYS, formatsFor, isDecidedField, shownFields, slotText, wizardLang, } from "@engenty-wizards/shared/definition";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { and, count, desc, eq, gte, inArray, max, or, sql } from "drizzle-orm";
|
|
4
4
|
import { canSpend, MICROS_PER_CREDIT } from "../credits/credits.js";
|
|
5
5
|
import { db, schema } from "../db/client.js";
|
|
@@ -18,7 +18,7 @@ export async function startTestRun(userId, wizardId, autopilot) {
|
|
|
18
18
|
const w = await ownedWizard(userId, wizardId);
|
|
19
19
|
const { definition, files } = await requireClean(w);
|
|
20
20
|
if (!(await canSpend())) {
|
|
21
|
-
throw new ServiceError("no_credits",
|
|
21
|
+
throw new ServiceError("no_credits", note("creditsUsedUp"));
|
|
22
22
|
}
|
|
23
23
|
const runId = await createRun({
|
|
24
24
|
wizardId: w.id,
|
|
@@ -80,13 +80,10 @@ function fly(runId, answers, acceptReviews) {
|
|
|
80
80
|
} while (again);
|
|
81
81
|
}
|
|
82
82
|
catch (err) {
|
|
83
|
-
const answers = (lang) => err instanceof RunInputError
|
|
84
|
-
? fieldErrorsIn(err.errors, lang)
|
|
85
|
-
.map((e) => `${e.field} – ${e.message}`)
|
|
86
|
-
.join("; ")
|
|
87
|
-
: "";
|
|
88
83
|
const message = err instanceof RunInputError
|
|
89
|
-
?
|
|
84
|
+
? note("answersMissing", {
|
|
85
|
+
answers: err.errors.map((e) => note("fieldError", { field: e.field, message: e.message })),
|
|
86
|
+
})
|
|
90
87
|
: saidOf(err);
|
|
91
88
|
await emitEvent(runId, null, "error", message).catch(() => undefined);
|
|
92
89
|
land();
|
|
@@ -377,7 +374,7 @@ export async function startRun(userId, wizardId, answers = {}) {
|
|
|
377
374
|
throw notFound();
|
|
378
375
|
}
|
|
379
376
|
if (!(await canSpend())) {
|
|
380
|
-
throw new ServiceError("no_credits",
|
|
377
|
+
throw new ServiceError("no_credits", note("creditsUsedUp"));
|
|
381
378
|
}
|
|
382
379
|
const runId = await createRun({
|
|
383
380
|
wizardId: w.id,
|
|
@@ -391,7 +388,7 @@ export async function startRun(userId, wizardId, answers = {}) {
|
|
|
391
388
|
throw new ServiceError("refused", saidOf(err));
|
|
392
389
|
}
|
|
393
390
|
if (err instanceof NoCreditsError) {
|
|
394
|
-
throw new ServiceError("no_credits",
|
|
391
|
+
throw new ServiceError("no_credits", note("creditsUsedUp"));
|
|
395
392
|
}
|
|
396
393
|
throw err;
|
|
397
394
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
2
2
|
import { and, eq, isNotNull, lt } from "drizzle-orm";
|
|
3
3
|
import { nanoid } from "nanoid";
|
|
4
4
|
import { db, schema } from "../db/client.js";
|
|
@@ -13,7 +13,7 @@ export const shareUrlFor = (token) => `${env.publicUrl}/s/${token}`;
|
|
|
13
13
|
/** Shares a finished run. Idempotent: the same run keeps the same link. */
|
|
14
14
|
export async function shareRun(run) {
|
|
15
15
|
if (run.status !== "done") {
|
|
16
|
-
throw new ServiceError("refused",
|
|
16
|
+
throw new ServiceError("refused", note("onlyFinishedResultsShared"));
|
|
17
17
|
}
|
|
18
18
|
let token = run.shareToken;
|
|
19
19
|
if (!token) {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { factKey, PROJECT_LIMITS } from "@engenty-wizards/shared/projects";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { nanoid } from "nanoid";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { runStudioAssistant } from "../agents/studio-assistant.js";
|
|
6
6
|
import { canSpend } from "../credits/credits.js";
|
|
7
7
|
import { errorText } from "../model-errors.js";
|
|
8
8
|
import { currentTenant } from "../tenants/tenant.js";
|
|
9
|
+
import { serverText } from "../texts.js";
|
|
9
10
|
import { projectWritable, requireWritable } from "./access.js";
|
|
10
11
|
import { apiSpace, apiSpaceDetails } from "./api.js";
|
|
11
12
|
import { openChat, turnHistory } from "./assistant-chats.js";
|
|
@@ -167,15 +168,13 @@ function assistMessage(input) {
|
|
|
167
168
|
}
|
|
168
169
|
async function work(job, projectId, input) {
|
|
169
170
|
try {
|
|
170
|
-
const
|
|
171
|
-
job.activity =
|
|
172
|
-
? "Übernimmt die Angaben der Website …"
|
|
173
|
-
: "Taking over what the website says …";
|
|
171
|
+
const lang = siteLang(input);
|
|
172
|
+
job.activity = serverText(lang, "siteTakingOver");
|
|
174
173
|
await fillFromSite(job.userId, projectId, input);
|
|
175
|
-
job.activity =
|
|
174
|
+
job.activity = serverText(lang, "siteWritingPages");
|
|
176
175
|
job.pages = await writePages(projectId, input);
|
|
177
176
|
if (input.assist && (await canSpend())) {
|
|
178
|
-
job.activity =
|
|
177
|
+
job.activity = serverText(lang, "siteReading");
|
|
179
178
|
const project = await ownedProject(job.userId, projectId);
|
|
180
179
|
// The person's open assistant chat gives the context; the turn is not stored in it.
|
|
181
180
|
const chat = await openChat(job.user);
|
|
@@ -210,9 +209,7 @@ async function work(job, projectId, input) {
|
|
|
210
209
|
job.error =
|
|
211
210
|
err instanceof ServiceError
|
|
212
211
|
? errorText(err, siteLang(input))
|
|
213
|
-
: siteLang(input)
|
|
214
|
-
? "Die Website ließ sich nicht übernehmen."
|
|
215
|
-
: "The website could not be taken over.";
|
|
212
|
+
: serverText(siteLang(input), "siteFailed");
|
|
216
213
|
console.error("[site]", err);
|
|
217
214
|
}
|
|
218
215
|
}
|
|
@@ -267,7 +264,7 @@ function siteJobView(job) {
|
|
|
267
264
|
export function siteJob(jobId) {
|
|
268
265
|
const job = jobs.get(jobId);
|
|
269
266
|
if (!job || job.tenantId !== currentTenant()) {
|
|
270
|
-
throw new ServiceError("not_found",
|
|
267
|
+
throw new ServiceError("not_found", note("jobNotExistAlready"));
|
|
271
268
|
}
|
|
272
269
|
return siteJobView(job);
|
|
273
270
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CATEGORY_TYPES, dayOf, } from "@engenty-wizards/shared/knowledge";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { and, asc, eq, inArray, isNotNull, or, sql } from "drizzle-orm";
|
|
4
4
|
import { nanoid } from "nanoid";
|
|
5
5
|
import { db, schema } from "../db/client.js";
|
|
@@ -273,10 +273,10 @@ const MAX_CATEGORIES = 60;
|
|
|
273
273
|
function checkDraft(draft) {
|
|
274
274
|
const name = draft.name.replace(/\s+/g, " ").trim().slice(0, 80);
|
|
275
275
|
if (!name) {
|
|
276
|
-
throw new ServiceError("invalid",
|
|
276
|
+
throw new ServiceError("invalid", note("categoryNeedsName"));
|
|
277
277
|
}
|
|
278
278
|
if (!CATEGORY_TYPES.includes(draft.type)) {
|
|
279
|
-
throw new ServiceError("invalid",
|
|
279
|
+
throw new ServiceError("invalid", note("unknownCategoryType", { type: draft.type }));
|
|
280
280
|
}
|
|
281
281
|
return name;
|
|
282
282
|
}
|
|
@@ -330,7 +330,7 @@ export async function putCategory(projectId, draft, opts = {}) {
|
|
|
330
330
|
return known;
|
|
331
331
|
}
|
|
332
332
|
if (rows.length >= MAX_CATEGORIES) {
|
|
333
|
-
throw new ServiceError("refused",
|
|
333
|
+
throw new ServiceError("refused", note("spaceMostCategories", { count: MAX_CATEGORIES }));
|
|
334
334
|
}
|
|
335
335
|
const id = nanoid(12);
|
|
336
336
|
const [row] = await db
|
|
@@ -409,7 +409,7 @@ export async function updateCategory(categoryId, patch) {
|
|
|
409
409
|
if (name !== row.name) {
|
|
410
410
|
const clash = byName(await categoryRows(row.projectId), name);
|
|
411
411
|
if (clash && clash.id !== row.id) {
|
|
412
|
-
throw new ServiceError("invalid",
|
|
412
|
+
throw new ServiceError("invalid", note("categoryAlreadyExists", { name }));
|
|
413
413
|
}
|
|
414
414
|
}
|
|
415
415
|
await db
|
|
@@ -459,7 +459,7 @@ export async function addCategoryValue(categoryId, value) {
|
|
|
459
459
|
const category = await categoryRow(categoryId);
|
|
460
460
|
await requireWritableProject(category.projectId);
|
|
461
461
|
if (category.type !== "choice") {
|
|
462
|
-
throw new ServiceError("invalid",
|
|
462
|
+
throw new ServiceError("invalid", note("onlyChoiceCategoriesValues"));
|
|
463
463
|
}
|
|
464
464
|
const ids = await addValues(category.id, [value]);
|
|
465
465
|
return { id: [...ids.values()].at(-1) };
|
|
@@ -489,7 +489,7 @@ export async function mergeCategoryValues(fromId, intoId) {
|
|
|
489
489
|
const from = await valueRow(fromId);
|
|
490
490
|
const into = await valueRow(intoId);
|
|
491
491
|
if (from.category.id !== into.category.id || fromId === intoId) {
|
|
492
|
-
throw new ServiceError("invalid",
|
|
492
|
+
throw new ServiceError("invalid", note("onlyValuesOneCategory"));
|
|
493
493
|
}
|
|
494
494
|
await requireWritableProject(from.category.projectId);
|
|
495
495
|
const t = schema.spaceItemCategory;
|