wizards 0.5.7 → 0.5.8
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-BcTtA42P.js +1 -0
- package/apps/web/dist/assets/{ChangelogDialog-rAtYZjxz.js → ChangelogDialog-DMOWV_Iu.js} +1 -1
- package/apps/web/dist/assets/ChatView-CrnrYHjp.js +10 -0
- package/apps/web/dist/assets/EditorPage-DpEw3eOu.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-DipH0Vec.js} +2 -2
- package/apps/web/dist/assets/{NewWizardChannels-BxrBhC9U.js → NewWizardChannels-DShu0PP6.js} +1 -1
- package/apps/web/dist/assets/NewWizardPage-HSa6PNJs.js +7 -0
- package/apps/web/dist/assets/{OnboardingPage-DPdH9sSj.js → OnboardingPage-CPADMs4c.js} +1 -1
- package/apps/web/dist/assets/ProjectPage-DMPcrhgt.js +1 -0
- package/apps/web/dist/assets/{PublicRunner-Bv3TMKw4.js → PublicRunner-DZ5sWmtg.js} +1 -1
- package/apps/web/dist/assets/{ReadOnly-CmqIrOAR.js → ReadOnly-B9xaq_M3.js} +1 -1
- package/apps/web/dist/assets/RunDrawer-9nMGhbSm.js +4 -0
- package/apps/web/dist/assets/{RunnerView-Cd1VAlIA.js → RunnerView-NSSP3tc6.js} +1 -1
- package/apps/web/dist/assets/SettingsPage-Dy9MbwQh.js +1 -0
- package/apps/web/dist/assets/SetupPage-kemgI7v5.js +1 -0
- package/apps/web/dist/assets/{SharePage-BT80wI1I.js → SharePage-CQfIdcwy.js} +1 -1
- package/apps/web/dist/assets/changelog-BW40vzI6.js +1 -0
- package/apps/web/dist/assets/{esm-BTVd6EFo.js → esm-BF1nonbH.js} +1 -1
- package/apps/web/dist/assets/index-DQ9qAB4v.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/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 +1 -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 { createHash } from "node:crypto";
|
|
2
|
-
import { wizardLang } from "@engenty-wizards/shared/definition";
|
|
2
|
+
import { LANGS, wizardLang } from "@engenty-wizards/shared/definition";
|
|
3
3
|
import { noteText } from "@engenty-wizards/shared/run";
|
|
4
4
|
import { and, asc, eq, inArray, isNotNull } from "drizzle-orm";
|
|
5
5
|
import { db, schema, withTenant } from "../db/client.js";
|
|
@@ -67,9 +67,7 @@ export function runsApiFor(pluginId) {
|
|
|
67
67
|
throw new ServiceError("refused", errorText(err, wizardLang(version.definition)));
|
|
68
68
|
}
|
|
69
69
|
if (err instanceof NoCreditsError) {
|
|
70
|
-
throw new ServiceError("no_credits", wizardLang(version.definition)
|
|
71
|
-
? "Dieser Wizard hat gerade kein Guthaben mehr. Versuch es später noch einmal."
|
|
72
|
-
: "This wizard has run out of credits for now. Try again later.");
|
|
70
|
+
throw new ServiceError("no_credits", noteText({ code: "wizardRunOutCredits" }, wizardLang(version.definition)));
|
|
73
71
|
}
|
|
74
72
|
throw err;
|
|
75
73
|
});
|
|
@@ -157,7 +155,7 @@ export function runsApiFor(pluginId) {
|
|
|
157
155
|
note: event.note
|
|
158
156
|
? {
|
|
159
157
|
code: event.note.code,
|
|
160
|
-
text:
|
|
158
|
+
text: Object.fromEntries(LANGS.map((lang) => [lang, noteText(event.note, lang)])),
|
|
161
159
|
}
|
|
162
160
|
: null,
|
|
163
161
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
2
2
|
import { PACKAGE_MIME } from "@engenty-wizards/shared/wizard-package";
|
|
3
3
|
import { Hono } from "hono";
|
|
4
4
|
import { bodyLimit } from "hono/body-limit";
|
|
@@ -20,7 +20,7 @@ import { siteJob, siteSchema, startSiteJob } from "../services/site.js";
|
|
|
20
20
|
import { checkOnServer, checkSchema, listSyncedSpaces, patchSyncedWizard, removeSyncedSpace, removeSyncedWizard, rotateSyncedLink, syncDataSchema, syncSettingsSchema, syncSpaceData, syncWizard, syncWizardSchema, } from "../services/spaces.js";
|
|
21
21
|
import { createWizard, ownedWizard, publishWizard, writeDraft } from "../services/wizards.js";
|
|
22
22
|
import { codeOf, tenantStatus } from "../tenants/control.js";
|
|
23
|
-
import {
|
|
23
|
+
import { notFoundAnswer, say } from "./lang.js";
|
|
24
24
|
import { dispatchAs } from "./plugins.js";
|
|
25
25
|
const importSchema = z.object({
|
|
26
26
|
/** An earlier import's wizard: it is updated instead of a new one being made. */
|
|
@@ -61,7 +61,7 @@ async function caller(c, scopes) {
|
|
|
61
61
|
}
|
|
62
62
|
if ((await tenantStatus(who.tenantId)) === "suspended") {
|
|
63
63
|
return c.json({
|
|
64
|
-
error:
|
|
64
|
+
error: say(c, "accountSuspended"),
|
|
65
65
|
code: "tenant_suspended",
|
|
66
66
|
}, 403);
|
|
67
67
|
}
|
|
@@ -72,7 +72,7 @@ function withinSyncLimit(c, who) {
|
|
|
72
72
|
return allowed(`sync:${who.tenantId}`, 240, HOUR)
|
|
73
73
|
? null
|
|
74
74
|
: c.json({
|
|
75
|
-
error:
|
|
75
|
+
error: say(c, "tooManyTransfersTry"),
|
|
76
76
|
code: "rate_limited",
|
|
77
77
|
}, 429);
|
|
78
78
|
}
|
|
@@ -90,7 +90,7 @@ async function pluginCall(c) {
|
|
|
90
90
|
if (!(await pluginIdsOf(who.tenantId)).has(id)) {
|
|
91
91
|
return loadedPlugin(id) || PRO_PLUGINS.includes(id)
|
|
92
92
|
? c.json({
|
|
93
|
-
error:
|
|
93
|
+
error: say(c, "pluginNotPartPlan"),
|
|
94
94
|
code: "plugin",
|
|
95
95
|
plugin: id,
|
|
96
96
|
}, 403)
|
|
@@ -180,7 +180,7 @@ export const apiRoutes = new Hono()
|
|
|
180
180
|
});
|
|
181
181
|
if (!found) {
|
|
182
182
|
return c.json({
|
|
183
|
-
error:
|
|
183
|
+
error: say(c, "wizardNotPublishedYet"),
|
|
184
184
|
code: "not_found",
|
|
185
185
|
}, 404);
|
|
186
186
|
}
|
|
@@ -290,7 +290,7 @@ export const apiRoutes = new Hono()
|
|
|
290
290
|
}
|
|
291
291
|
if (!allowed(`site:${who.tenantId}`, 20, HOUR)) {
|
|
292
292
|
return c.json({
|
|
293
|
-
error:
|
|
293
|
+
error: say(c, "tooManyTimesRow"),
|
|
294
294
|
code: "rate_limited",
|
|
295
295
|
}, 429);
|
|
296
296
|
}
|
|
@@ -396,7 +396,7 @@ export const apiRoutes = new Hono()
|
|
|
396
396
|
}
|
|
397
397
|
if ((await tenantStatus(who.tenantId)) === "suspended") {
|
|
398
398
|
return c.json({
|
|
399
|
-
error:
|
|
399
|
+
error: say(c, "accountSuspended"),
|
|
400
400
|
code: "tenant_suspended",
|
|
401
401
|
}, 403);
|
|
402
402
|
}
|
|
@@ -427,7 +427,7 @@ export const apiRoutes = new Hono()
|
|
|
427
427
|
return c.json({ wizardId, revision: written.revision, issues: written.issues });
|
|
428
428
|
}
|
|
429
429
|
if (written.issues.length) {
|
|
430
|
-
throw new ServiceError("has_issues",
|
|
430
|
+
throw new ServiceError("has_issues", note("wizardStillErrors"), {
|
|
431
431
|
issues: written.issues,
|
|
432
432
|
wizardId,
|
|
433
433
|
});
|
|
@@ -1,20 +1,25 @@
|
|
|
1
|
+
import { localLang } from "@engenty-wizards/shared/definition";
|
|
2
|
+
import { serverText } from "../texts.js";
|
|
1
3
|
/**
|
|
2
|
-
* The language a visitor's request asks for
|
|
3
|
-
* first
|
|
4
|
-
*
|
|
4
|
+
* The language a visitor's request asks for, as the studio starts in it (`localLang`): the
|
|
5
|
+
* first of the browser's languages engenty speaks other than English, else English. The
|
|
6
|
+
* browser's `Accept-Language` names them in its order; the server has no time zone to go by.
|
|
5
7
|
*/
|
|
6
8
|
export function requestLang(c) {
|
|
7
|
-
const asked = c.req.header("accept-language")
|
|
8
|
-
|
|
9
|
+
const asked = (c.req.header("accept-language") ?? "")
|
|
10
|
+
.split(",")
|
|
11
|
+
.map((part) => part.split(";")[0]?.trim() ?? "")
|
|
12
|
+
.filter(Boolean);
|
|
13
|
+
return localLang(asked) ?? "en";
|
|
9
14
|
}
|
|
10
|
-
/** A line the person reads, in the language their request asks for. */
|
|
11
|
-
export function
|
|
12
|
-
return requestLang(c)
|
|
15
|
+
/** A line of the server's table the person reads, in the language their request asks for. */
|
|
16
|
+
export function say(c, key, params) {
|
|
17
|
+
return serverText(requestLang(c), key, params);
|
|
13
18
|
}
|
|
14
19
|
/** A 404 the person may read: a sentence in their language, the machine code beside it. */
|
|
15
20
|
export function notFoundAnswer(c) {
|
|
16
21
|
return {
|
|
17
|
-
error:
|
|
22
|
+
error: say(c, "notFound"),
|
|
18
23
|
code: "not_found",
|
|
19
24
|
};
|
|
20
25
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FORMATS, LIST_FORMATS, TEXT_CLASSES } from "@engenty-wizards/shared/definition";
|
|
1
|
+
import { FORMATS, LANGS, LIST_FORMATS, TEXT_CLASSES } from "@engenty-wizards/shared/definition";
|
|
2
2
|
import { TableColumnValueError } from "@engenty-wizards/shared/engenty/data-tables";
|
|
3
3
|
import { noteText } from "@engenty-wizards/shared/run";
|
|
4
4
|
import { getConnInfo } from "@hono/node-server/conninfo";
|
|
@@ -39,7 +39,7 @@ import { isIconFile, wizardAvatarSvg, wizardIcon } from "../services/wizard-icon
|
|
|
39
39
|
import { clearStore, deleteRows, listRows, listSecrets, readStoreFile, StoreError, saveRows, scopeOf, storeFiles, updateRow, } from "../store/index.js";
|
|
40
40
|
import { tenantOfLink, tenantOfRun, tenantStatus, tokenOfCode, visitorOverLimit, } from "../tenants/control.js";
|
|
41
41
|
import { bareMime, byteRange, inlineSafe, uploadLimit, uploadMime, wizardManifest, } from "./delivery.js";
|
|
42
|
-
import {
|
|
42
|
+
import { notFoundAnswer, requestLang, say } from "./lang.js";
|
|
43
43
|
const VISITOR_COOKIE = "wz_vid";
|
|
44
44
|
/** Kept files a review shows inline. */
|
|
45
45
|
const INLINE_TYPES = new Set(["application/pdf", "image/png", "image/jpeg", "image/webp"]);
|
|
@@ -205,7 +205,7 @@ export const publicRoutes = new Hono()
|
|
|
205
205
|
const ip = clientIp(c);
|
|
206
206
|
if (codeLookupBlocked(ip)) {
|
|
207
207
|
return c.json({
|
|
208
|
-
error:
|
|
208
|
+
error: say(c, "tooManyTriesWait"),
|
|
209
209
|
code: "too_many_tries",
|
|
210
210
|
}, 429);
|
|
211
211
|
}
|
|
@@ -633,7 +633,7 @@ export const runRoutes = new Hono()
|
|
|
633
633
|
.object({
|
|
634
634
|
lat: z.number().min(-90).max(90),
|
|
635
635
|
lng: z.number().min(-180).max(180),
|
|
636
|
-
language: z.enum(
|
|
636
|
+
language: z.enum(LANGS).default("en"),
|
|
637
637
|
})
|
|
638
638
|
.parse(await c.req.json());
|
|
639
639
|
return c.json({ label: await reverseGeocode(lat, lng, language) });
|
|
@@ -1012,7 +1012,7 @@ export const runRoutes = new Hono()
|
|
|
1012
1012
|
.object({
|
|
1013
1013
|
token: z.string().min(8).max(512),
|
|
1014
1014
|
platform: z.enum(["ios", "android"]),
|
|
1015
|
-
lang: z.enum(
|
|
1015
|
+
lang: z.enum(LANGS).default("en"),
|
|
1016
1016
|
})
|
|
1017
1017
|
.parse(await c.req.json());
|
|
1018
1018
|
await setPushDevice(run.id, body);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { mkdirSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { ASSISTANT_LAYOUTS, ASSISTANT_PAGE_BYTES, assistantSignalSchema, assistantTurnSchema, } from "@engenty-wizards/shared/assistant";
|
|
4
|
-
import { MODEL_CLASSES, TEXT_CLASSES, } from "@engenty-wizards/shared/definition";
|
|
4
|
+
import { LANGS, MODEL_CLASSES, TEXT_CLASSES, } from "@engenty-wizards/shared/definition";
|
|
5
5
|
import { CATEGORY_TYPES, whereSchema } from "@engenty-wizards/shared/knowledge";
|
|
6
6
|
import { PROJECT_FILE_KINDS } from "@engenty-wizards/shared/projects";
|
|
7
7
|
import { isCreditsRef } from "@engenty-wizards/shared/providers";
|
|
8
|
-
import {
|
|
8
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
9
9
|
import { PACKAGE_EXTENSION, PACKAGE_MAX_BYTES, PACKAGE_MIME, } from "@engenty-wizards/shared/wizard-package";
|
|
10
10
|
import { generateText } from "ai";
|
|
11
11
|
import { Hono } from "hono";
|
|
@@ -63,9 +63,10 @@ import { createWizard, deleteWizard, draftChanges, duplicateWizard, listWizards,
|
|
|
63
63
|
import { readSetting, writeSetting } from "../settings.js";
|
|
64
64
|
import { codeOf } from "../tenants/control.js";
|
|
65
65
|
import { currentTenant } from "../tenants/tenant.js";
|
|
66
|
+
import { serverText } from "../texts.js";
|
|
66
67
|
import { applyUpdate, updateStatus } from "../update.js";
|
|
67
68
|
import { byteRange } from "./delivery.js";
|
|
68
|
-
import {
|
|
69
|
+
import { requestLang, say } from "./lang.js";
|
|
69
70
|
/** The model sources a test call has worked on: the setup is done for those, not for the others. */
|
|
70
71
|
async function testedSources() {
|
|
71
72
|
const tested = await readSetting("setup-done");
|
|
@@ -282,7 +283,7 @@ export const studio = new Hono()
|
|
|
282
283
|
.get("/team", async (c) => {
|
|
283
284
|
if (!managed) {
|
|
284
285
|
return c.json({
|
|
285
|
-
error:
|
|
286
|
+
error: say(c, "onlyAvailableCloud"),
|
|
286
287
|
code: "not_managed",
|
|
287
288
|
}, 404);
|
|
288
289
|
}
|
|
@@ -304,14 +305,14 @@ export const studio = new Hono()
|
|
|
304
305
|
// `?fresh=1` asks GitHub now instead of within the hour.
|
|
305
306
|
.get("/update", async (c) => managed
|
|
306
307
|
? c.json({
|
|
307
|
-
error:
|
|
308
|
+
error: say(c, "onlyAvailableComputer"),
|
|
308
309
|
code: "not_local",
|
|
309
310
|
}, 404)
|
|
310
311
|
: c.json(await updateStatus(c.req.query("fresh") === "1")))
|
|
311
312
|
.post("/update", async (c) => {
|
|
312
313
|
if (managed) {
|
|
313
314
|
return c.json({
|
|
314
|
-
error:
|
|
315
|
+
error: say(c, "onlyAvailableComputer"),
|
|
315
316
|
code: "not_local",
|
|
316
317
|
}, 404);
|
|
317
318
|
}
|
|
@@ -320,7 +321,7 @@ export const studio = new Hono()
|
|
|
320
321
|
})
|
|
321
322
|
.put("/profile", async (c) => c.json(await saveProfile(c.get("user"), profileSchema.parse(await c.req.json()))))
|
|
322
323
|
.put("/lang", async (c) => {
|
|
323
|
-
const { lang } = z.object({ lang: z.enum(
|
|
324
|
+
const { lang } = z.object({ lang: z.enum(LANGS) }).parse(await c.req.json());
|
|
324
325
|
await saveUserLang(c.get("user"), lang);
|
|
325
326
|
return c.json({ lang });
|
|
326
327
|
})
|
|
@@ -342,10 +343,10 @@ export const studio = new Hono()
|
|
|
342
343
|
.post("/assistant/speak", async (c) => {
|
|
343
344
|
const { text } = z.object({ text: z.string().min(1).max(4000) }).parse(await c.req.json());
|
|
344
345
|
if ((await classWays()).speech.kind === "none") {
|
|
345
|
-
throw new ServiceError("refused",
|
|
346
|
+
throw new ServiceError("refused", note("noLanguageModelSet"));
|
|
346
347
|
}
|
|
347
348
|
if (!(await canSpend())) {
|
|
348
|
-
throw new ServiceError("no_credits",
|
|
349
|
+
throw new ServiceError("no_credits", note("creditsUsedUp"));
|
|
349
350
|
}
|
|
350
351
|
const voice = await generateSpeechMedia({ text, abortSignal: c.req.raw.signal });
|
|
351
352
|
return c.body(new Uint8Array(voice.bytes), 200, { "content-type": voice.mime });
|
|
@@ -365,10 +366,10 @@ export const studio = new Hono()
|
|
|
365
366
|
.post("/assistant/turn", async (c) => {
|
|
366
367
|
const user = c.get("user");
|
|
367
368
|
const body = assistantTurnSchema
|
|
368
|
-
.extend({ lang: z.enum(
|
|
369
|
+
.extend({ lang: z.enum(LANGS).default("en") })
|
|
369
370
|
.parse(await c.req.json());
|
|
370
371
|
if (!(await canSpend())) {
|
|
371
|
-
throw new ServiceError("no_credits",
|
|
372
|
+
throw new ServiceError("no_credits", note("creditsUsedUp"));
|
|
372
373
|
}
|
|
373
374
|
const project = body.projectId ? await ownedProject(user.id, body.projectId) : null;
|
|
374
375
|
const writable = project ? await projectWritable(project) : false;
|
|
@@ -454,7 +455,7 @@ export const studio = new Hono()
|
|
|
454
455
|
const left = takeSignals(runId);
|
|
455
456
|
if (!left.length || abort.signal.aborted) {
|
|
456
457
|
changed ||= result.changed;
|
|
457
|
-
reply = result.reply || (changed ? (body.lang
|
|
458
|
+
reply = result.reply || (changed ? serverText(body.lang, "done") : "");
|
|
458
459
|
const stored = await addMessage(chat.id, {
|
|
459
460
|
role: "assistant",
|
|
460
461
|
content: reply,
|
|
@@ -480,9 +481,7 @@ export const studio = new Hono()
|
|
|
480
481
|
await send("error", {
|
|
481
482
|
message: err instanceof ServiceError || err instanceof ModelUnavailableError
|
|
482
483
|
? errorText(err, body.lang)
|
|
483
|
-
: body.lang
|
|
484
|
-
? "Da ist etwas schiefgelaufen. Versuch es noch einmal."
|
|
485
|
-
: "Something went wrong. Try again.",
|
|
484
|
+
: serverText(body.lang, "somethingWrong"),
|
|
486
485
|
});
|
|
487
486
|
}
|
|
488
487
|
endRun(runId);
|
|
@@ -530,7 +529,7 @@ export const studio = new Hono()
|
|
|
530
529
|
const kind = z.enum(PROJECT_FILE_KINDS).parse(c.req.query("kind"));
|
|
531
530
|
const file = (await c.req.formData()).get("file");
|
|
532
531
|
if (!(file instanceof File)) {
|
|
533
|
-
throw new ServiceError("invalid",
|
|
532
|
+
throw new ServiceError("invalid", note("chooseFile"));
|
|
534
533
|
}
|
|
535
534
|
const row = await addProjectFile(project.id, {
|
|
536
535
|
kind,
|
|
@@ -563,7 +562,7 @@ export const studio = new Hono()
|
|
|
563
562
|
await ownedProject(c.get("user").id, c.req.param("id"));
|
|
564
563
|
const { url } = z.object({ url: z.string().min(1).max(2000) }).parse(await c.req.json());
|
|
565
564
|
const colors = await scanColors(url).catch(() => {
|
|
566
|
-
throw new ServiceError("invalid",
|
|
565
|
+
throw new ServiceError("invalid", note("pageNotReached"));
|
|
567
566
|
});
|
|
568
567
|
return c.json({ colors });
|
|
569
568
|
})
|
|
@@ -579,7 +578,7 @@ export const studio = new Hono()
|
|
|
579
578
|
})
|
|
580
579
|
.parse(await c.req.json());
|
|
581
580
|
if (!(await canSpend())) {
|
|
582
|
-
throw new ServiceError("no_credits",
|
|
581
|
+
throw new ServiceError("no_credits", note("creditsUsedUp"));
|
|
583
582
|
}
|
|
584
583
|
try {
|
|
585
584
|
return c.json({
|
|
@@ -597,7 +596,7 @@ export const studio = new Hono()
|
|
|
597
596
|
await ownedProject(c.get("user").id, c.req.param("id"));
|
|
598
597
|
const { url } = z.object({ url: z.string().min(1).max(2000) }).parse(await c.req.json());
|
|
599
598
|
const fonts = await scanFonts(url).catch(() => {
|
|
600
|
-
throw new ServiceError("invalid",
|
|
599
|
+
throw new ServiceError("invalid", note("pageNotReached"));
|
|
601
600
|
});
|
|
602
601
|
return c.json({ fonts });
|
|
603
602
|
})
|
|
@@ -839,7 +838,7 @@ export const studio = new Hono()
|
|
|
839
838
|
? { fileId: id }
|
|
840
839
|
: null;
|
|
841
840
|
if (!ref || key[1] !== ":") {
|
|
842
|
-
throw new ServiceError("invalid",
|
|
841
|
+
throw new ServiceError("invalid", note("unknownEntry"));
|
|
843
842
|
}
|
|
844
843
|
const { values } = z
|
|
845
844
|
.object({ values: z.array(z.union([z.string().max(300), z.number(), z.boolean()])).max(50) })
|
|
@@ -953,7 +952,7 @@ export const studio = new Hono()
|
|
|
953
952
|
.post("/projects/:id/wizards/import", async (c) => {
|
|
954
953
|
const file = (await c.req.formData()).get("file");
|
|
955
954
|
if (!(file instanceof File) || !file.size || file.size > PACKAGE_MAX_BYTES) {
|
|
956
|
-
throw new ServiceError("invalid",
|
|
955
|
+
throw new ServiceError("invalid", note("chooseWizardFileMb", { PACKAGE_EXTENSION }));
|
|
957
956
|
}
|
|
958
957
|
return c.json(await importWizard(c.get("user").id, c.req.param("id"), new Uint8Array(await file.arrayBuffer()), file.name, requestLang(c)));
|
|
959
958
|
})
|
|
@@ -964,7 +963,7 @@ export const studio = new Hono()
|
|
|
964
963
|
});
|
|
965
964
|
if (!found) {
|
|
966
965
|
return c.json({
|
|
967
|
-
error:
|
|
966
|
+
error: say(c, "wizardNotPublishedYet"),
|
|
968
967
|
}, 404);
|
|
969
968
|
}
|
|
970
969
|
const { name, zip } = found;
|
|
@@ -1116,7 +1115,7 @@ export const studio = new Hono()
|
|
|
1116
1115
|
.parse(await c.req.json());
|
|
1117
1116
|
await writableWizard(user.id, wizardId);
|
|
1118
1117
|
if (!(await canSpend())) {
|
|
1119
|
-
throw new ServiceError("no_credits",
|
|
1118
|
+
throw new ServiceError("no_credits", note("creditsUsedUp"));
|
|
1120
1119
|
}
|
|
1121
1120
|
return streamSSE(c, async (stream) => {
|
|
1122
1121
|
const abort = new AbortController();
|
|
@@ -1146,7 +1145,7 @@ export const studio = new Hono()
|
|
|
1146
1145
|
data: JSON.stringify({
|
|
1147
1146
|
message: err instanceof ServiceError
|
|
1148
1147
|
? errorText(err, requestLang(c))
|
|
1149
|
-
:
|
|
1148
|
+
: say(c, "somethingWentWrongTry"),
|
|
1150
1149
|
}),
|
|
1151
1150
|
});
|
|
1152
1151
|
}
|
|
@@ -1156,10 +1155,10 @@ export const studio = new Hono()
|
|
|
1156
1155
|
.post("/transcribe", async (c) => {
|
|
1157
1156
|
const file = (await c.req.formData()).get("file");
|
|
1158
1157
|
if (!(file instanceof File) || !file.size || file.size > 10_000_000) {
|
|
1159
|
-
throw new ServiceError("invalid",
|
|
1158
|
+
throw new ServiceError("invalid", note("recordingMbMost"));
|
|
1160
1159
|
}
|
|
1161
1160
|
if (!(await canSpend())) {
|
|
1162
|
-
throw new ServiceError("no_credits",
|
|
1161
|
+
throw new ServiceError("no_credits", note("creditsUsedUp"));
|
|
1163
1162
|
}
|
|
1164
1163
|
try {
|
|
1165
1164
|
const { text } = await transcribeAudio({
|
|
@@ -1230,7 +1229,7 @@ export const studio = new Hono()
|
|
|
1230
1229
|
const { connect } = z.object({ connect: z.boolean() }).parse(await c.req.json());
|
|
1231
1230
|
const [done] = await connectApps(layout(), [c.req.param("id")], !connect);
|
|
1232
1231
|
if (!done) {
|
|
1233
|
-
return c.json({ error:
|
|
1232
|
+
return c.json({ error: say(c, "unknownApp"), code: "not_found" }, 404);
|
|
1234
1233
|
}
|
|
1235
1234
|
// Not done is an answer too: the app's file is no plain JSON, here is what to paste.
|
|
1236
1235
|
return c.json(done.outcome);
|
|
@@ -1251,7 +1250,7 @@ export const studio = new Hono()
|
|
|
1251
1250
|
.put("/models", async (c) => {
|
|
1252
1251
|
if (!mayChangeModels(c.get("user"))) {
|
|
1253
1252
|
return c.json({
|
|
1254
|
-
error:
|
|
1253
|
+
error: say(c, "onlyTeamAdminsChange"),
|
|
1255
1254
|
code: "forbidden",
|
|
1256
1255
|
}, 403);
|
|
1257
1256
|
}
|
|
@@ -1262,7 +1261,7 @@ export const studio = new Hono()
|
|
|
1262
1261
|
input.ollamaUrl ||
|
|
1263
1262
|
Object.values(input.bindings ?? {}).some((ref) => ref && !cloudBinding(ref)))) {
|
|
1264
1263
|
return c.json({
|
|
1265
|
-
error:
|
|
1264
|
+
error: say(c, "notAvailableCloud"),
|
|
1266
1265
|
code: "not_local",
|
|
1267
1266
|
}, 400);
|
|
1268
1267
|
}
|
|
@@ -1273,7 +1272,9 @@ export const studio = new Hono()
|
|
|
1273
1272
|
Object.values(input.bindings ?? {}).some((ref) => ref && !isCreditsRef(ref));
|
|
1274
1273
|
if (own && info && !feature("ownKeys", info.features)) {
|
|
1275
1274
|
return c.json({
|
|
1276
|
-
error:
|
|
1275
|
+
error: info.plan?.name
|
|
1276
|
+
? say(c, "ownKeysNotInPlan", { plan: info.plan.name })
|
|
1277
|
+
: say(c, "ownKeysNotInTeamPlan"),
|
|
1277
1278
|
code: "plan",
|
|
1278
1279
|
}, 403);
|
|
1279
1280
|
}
|
|
@@ -1291,7 +1292,7 @@ export const studio = new Hono()
|
|
|
1291
1292
|
if (!value) {
|
|
1292
1293
|
return c.json({
|
|
1293
1294
|
ok: false,
|
|
1294
|
-
message:
|
|
1295
|
+
message: say(c, "noApiKeySet"),
|
|
1295
1296
|
});
|
|
1296
1297
|
}
|
|
1297
1298
|
return c.json(await checkKey(provider, value, requestLang(c)));
|
|
@@ -1301,12 +1302,12 @@ export const studio = new Hono()
|
|
|
1301
1302
|
.post("/models/test", async (c) => {
|
|
1302
1303
|
if (!mayChangeModels(c.get("user"))) {
|
|
1303
1304
|
return c.json({
|
|
1304
|
-
error:
|
|
1305
|
+
error: say(c, "onlyTeamAdminsTest"),
|
|
1305
1306
|
code: "forbidden",
|
|
1306
1307
|
}, 403);
|
|
1307
1308
|
}
|
|
1308
1309
|
const { cls, lang } = z
|
|
1309
|
-
.object({ cls: z.enum(MODEL_CLASSES), lang: z.enum(
|
|
1310
|
+
.object({ cls: z.enum(MODEL_CLASSES), lang: z.enum(LANGS).default("en") })
|
|
1310
1311
|
.parse(await c.req.json());
|
|
1311
1312
|
return c.json(await testClass(cls, lang));
|
|
1312
1313
|
})
|
|
@@ -1461,7 +1462,7 @@ export const studio = new Hono()
|
|
|
1461
1462
|
.put("/team", async (c) => {
|
|
1462
1463
|
if (!managed) {
|
|
1463
1464
|
return c.json({
|
|
1464
|
-
error:
|
|
1465
|
+
error: say(c, "onlyAvailableCloud"),
|
|
1465
1466
|
code: "not_managed",
|
|
1466
1467
|
}, 404);
|
|
1467
1468
|
}
|
|
@@ -1473,7 +1474,7 @@ export const studio = new Hono()
|
|
|
1473
1474
|
.post("/onboarding/done", async (c) => {
|
|
1474
1475
|
if (!managed) {
|
|
1475
1476
|
return c.json({
|
|
1476
|
-
error:
|
|
1477
|
+
error: say(c, "onlyAvailableCloud"),
|
|
1477
1478
|
code: "not_managed",
|
|
1478
1479
|
}, 404);
|
|
1479
1480
|
}
|
|
@@ -1490,12 +1491,12 @@ export const studio = new Hono()
|
|
|
1490
1491
|
.post("/install-mail", async (c) => {
|
|
1491
1492
|
if (!managed) {
|
|
1492
1493
|
return c.json({
|
|
1493
|
-
error:
|
|
1494
|
+
error: say(c, "onlyAvailableCloud"),
|
|
1494
1495
|
code: "not_managed",
|
|
1495
1496
|
}, 404);
|
|
1496
1497
|
}
|
|
1497
1498
|
const { lang } = z
|
|
1498
|
-
.object({ lang: z.enum(
|
|
1499
|
+
.object({ lang: z.enum(LANGS).default("en") })
|
|
1499
1500
|
.parse(await c.req.json().catch(() => ({})));
|
|
1500
1501
|
await installMail(c.get("user").email, lang);
|
|
1501
1502
|
return c.json({ ok: true });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { and, eq } from "drizzle-orm";
|
|
4
4
|
import { db, schema } from "../db/client.js";
|
|
5
5
|
import { managed, tenantInfo } from "../manage.js";
|
|
@@ -31,7 +31,7 @@ export function currentRole() {
|
|
|
31
31
|
return actor.getStore() ?? "owner";
|
|
32
32
|
}
|
|
33
33
|
export const isAdminRole = (role) => role === "owner" || role === "admin";
|
|
34
|
-
export const MEMBERS_EDIT_ONLY =
|
|
34
|
+
export const MEMBERS_EDIT_ONLY = note("onlyTeamAdmins");
|
|
35
35
|
/** Refuses a member: making and deleting is for the owner and the admins of the team. */
|
|
36
36
|
export async function requireAdmin() {
|
|
37
37
|
if (syncing() || !managed || isAdminRole(currentRole())) {
|
|
@@ -52,8 +52,8 @@ export async function mayBuild() {
|
|
|
52
52
|
// An older Manage-App does not say: then it builds. One that cannot be reached: nothing changes.
|
|
53
53
|
return info ? info.limits.build !== false : false;
|
|
54
54
|
}
|
|
55
|
-
export const READ_ONLY_PROJECT =
|
|
56
|
-
export const READ_ONLY_TENANT =
|
|
55
|
+
export const READ_ONLY_PROJECT = note("spaceEditedLocally");
|
|
56
|
+
export const READ_ONLY_TENANT = note("wizardsRunOncePublished");
|
|
57
57
|
/** Refuses when the tenant builds nothing here. */
|
|
58
58
|
export async function requireBuild() {
|
|
59
59
|
if (syncing() || (await mayBuild())) {
|
|
@@ -5,6 +5,7 @@ import { listConnectors } from "../connectors/external.js";
|
|
|
5
5
|
import { db, schema } from "../db/client.js";
|
|
6
6
|
import { managed } from "../manage.js";
|
|
7
7
|
import { hasTextModel } from "../models.js";
|
|
8
|
+
import { serverText } from "../texts.js";
|
|
8
9
|
import { draftFiles, readFile } from "./files.js";
|
|
9
10
|
import { ownedProject } from "./projects.js";
|
|
10
11
|
import { addMessage, draftIssues, ownedWizard, wizardMessages, writableWizard } from "./wizards.js";
|
|
@@ -72,19 +73,9 @@ lang, io) {
|
|
|
72
73
|
images,
|
|
73
74
|
lang,
|
|
74
75
|
});
|
|
75
|
-
const de = lang === "de";
|
|
76
76
|
const reply = result.unfinished
|
|
77
|
-
? `${result.reply ? `${result.reply}\n\n` : ""}${
|
|
78
|
-
|
|
79
|
-
: "I have not quite finished. Write “continue” and I will carry on right there."}`
|
|
80
|
-
: result.reply ||
|
|
81
|
-
(result.changed
|
|
82
|
-
? de
|
|
83
|
-
? "Erledigt."
|
|
84
|
-
: "Done."
|
|
85
|
-
: de
|
|
86
|
-
? "Das habe ich nicht verstanden – magst du es anders formulieren?"
|
|
87
|
-
: "I did not understand that – could you put it differently?");
|
|
77
|
+
? `${result.reply ? `${result.reply}\n\n` : ""}${serverText(lang, "notFinished")}`
|
|
78
|
+
: result.reply || serverText(lang, result.changed ? "done" : "notUnderstood");
|
|
88
79
|
await addMessage(w.id, { role: "assistant", content: reply, changed: result.changed });
|
|
89
80
|
const after = await ownedWizard(userId, wizardId);
|
|
90
81
|
return {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ASSISTANT_LAYOUTS } from "@engenty-wizards/shared/assistant";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { generateText } from "ai";
|
|
4
4
|
import { and, asc, desc, eq, isNotNull, isNull, sql } from "drizzle-orm";
|
|
5
5
|
import { nanoid } from "nanoid";
|
|
@@ -253,7 +253,7 @@ export async function readChat(user, chatId) {
|
|
|
253
253
|
where: and(mine(user), eq(schema.assistantChat.id, chatId)),
|
|
254
254
|
});
|
|
255
255
|
if (!chat) {
|
|
256
|
-
throw new ServiceError("not_found",
|
|
256
|
+
throw new ServiceError("not_found", note("chatNotExist"));
|
|
257
257
|
}
|
|
258
258
|
return {
|
|
259
259
|
id: chat.id,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GRADIENT_TYPES, gradientCss, mainLogo, } from "@engenty-wizards/shared/projects";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { generateText, Output } from "ai";
|
|
4
4
|
import { and, asc, eq } from "drizzle-orm";
|
|
5
5
|
import { z } from "zod";
|
|
@@ -66,14 +66,14 @@ export async function describeGradient(brand, text, current) {
|
|
|
66
66
|
answer = result.output;
|
|
67
67
|
}
|
|
68
68
|
catch {
|
|
69
|
-
throw new ServiceError("invalid",
|
|
69
|
+
throw new ServiceError("invalid", note("gradientFailed"));
|
|
70
70
|
}
|
|
71
71
|
const stops = answer.stops
|
|
72
72
|
.filter((s) => HEX.test(s.color))
|
|
73
73
|
.slice(0, 12)
|
|
74
74
|
.map((s) => ({ color: s.color.toLowerCase(), at: Math.min(100, Math.max(0, s.at)) }));
|
|
75
75
|
if (stops.length < 2) {
|
|
76
|
-
throw new ServiceError("invalid",
|
|
76
|
+
throw new ServiceError("invalid", note("gradientFailed"));
|
|
77
77
|
}
|
|
78
78
|
return {
|
|
79
79
|
name: answer.name.trim().slice(0, 80),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { and, asc, eq, inArray, isNotNull, isNull, like } from "drizzle-orm";
|
|
4
4
|
import { accountToken, linkedAccount } from "../auth/account.js";
|
|
5
5
|
import { control, controlDb, db, schema } from "../db/client.js";
|
|
@@ -26,7 +26,7 @@ export async function cloudState(wizardId) {
|
|
|
26
26
|
async function call(method, path, body, timeoutMs = 30_000) {
|
|
27
27
|
const token = await accountToken();
|
|
28
28
|
if (!token) {
|
|
29
|
-
throw new ServiceError("refused",
|
|
29
|
+
throw new ServiceError("refused", note("accountSignedOut"), {
|
|
30
30
|
reason: "signed_out",
|
|
31
31
|
});
|
|
32
32
|
}
|
|
@@ -40,7 +40,7 @@ async function call(method, path, body, timeoutMs = 30_000) {
|
|
|
40
40
|
signal: AbortSignal.timeout(timeoutMs),
|
|
41
41
|
}).catch(() => null);
|
|
42
42
|
if (!res) {
|
|
43
|
-
throw new ServiceError("refused",
|
|
43
|
+
throw new ServiceError("refused", note("cloudNotReachedRight"), {
|
|
44
44
|
reason: "unreachable",
|
|
45
45
|
});
|
|
46
46
|
}
|
|
@@ -50,7 +50,7 @@ async function call(method, path, body, timeoutMs = 30_000) {
|
|
|
50
50
|
function refusal(answer, fallback) {
|
|
51
51
|
const { error, reason, ...rest } = answer.body;
|
|
52
52
|
const message = answer.status === 401
|
|
53
|
-
?
|
|
53
|
+
? note("accountSignedOut")
|
|
54
54
|
: typeof error === "string" && error
|
|
55
55
|
? error
|
|
56
56
|
: fallback;
|
|
@@ -214,7 +214,7 @@ export async function syncToCloud(userId, wizardId) {
|
|
|
214
214
|
const w = await ownedWizard(userId, wizardId);
|
|
215
215
|
const version = await publishedVersion(w);
|
|
216
216
|
if (!version) {
|
|
217
|
-
throw new ServiceError("refused",
|
|
217
|
+
throw new ServiceError("refused", note("publishWizardFirst"));
|
|
218
218
|
}
|
|
219
219
|
const before = await cloudState(w.id);
|
|
220
220
|
try {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
2
2
|
import { errorText, NotedError } from "../model-errors.js";
|
|
3
3
|
const STATUS = {
|
|
4
4
|
not_found: 404,
|
|
@@ -26,4 +26,4 @@ export class ServiceError extends NotedError {
|
|
|
26
26
|
return { error: errorText(this, lang), code: this.code, ...this.data };
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
export const notFound = () => new ServiceError("not_found",
|
|
29
|
+
export const notFound = () => new ServiceError("not_found", note("notFound"));
|