wizards 0.5.6 → 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 +9 -7
- package/apps/runtime/dist/assistant/knows.js +10 -9
- package/apps/runtime/dist/auth/index.js +7 -0
- 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/marketplace.js +6 -1
- 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 +18 -8
- 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-sdSC9eZj.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-B4-ipMdE.js → FlowPreview-CzmH4JUQ.js} +1 -1
- package/apps/web/dist/assets/{Harness-DwI4wFqj.js → Harness-DipH0Vec.js} +2 -2
- package/apps/web/dist/assets/{NewWizardChannels-DkI648G-.js → NewWizardChannels-DShu0PP6.js} +1 -1
- package/apps/web/dist/assets/NewWizardPage-HSa6PNJs.js +7 -0
- package/apps/web/dist/assets/OnboardingPage-CPADMs4c.js +1 -0
- package/apps/web/dist/assets/ProjectPage-DMPcrhgt.js +1 -0
- package/apps/web/dist/assets/PublicRunner-DZ5sWmtg.js +1 -0
- package/apps/web/dist/assets/{ReadOnly-Jvzgyelg.js → ReadOnly-B9xaq_M3.js} +1 -1
- package/apps/web/dist/assets/RunDrawer-9nMGhbSm.js +4 -0
- package/apps/web/dist/assets/{RunnerView-DN4sMYS6.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-CmowpiJG.js → SharePage-CQfIdcwy.js} +1 -1
- package/apps/web/dist/assets/{changelog-Cz8fZ-jG.js → changelog-BW40vzI6.js} +1 -1
- package/apps/web/dist/assets/{esm-J06O1nN_.js → esm-BF1nonbH.js} +1 -1
- package/apps/web/dist/assets/index-CnJ4Yzkf.css +1 -0
- package/apps/web/dist/assets/index-DQ9qAB4v.js +14 -0
- package/apps/web/dist/assets/{lock-ChDlFFHO.js → lock-DVvM6IsA.js} +1 -1
- package/apps/web/dist/assets/{phone-Cr7jz_kf.js → phone-3fG1okFs.js} +1 -1
- package/apps/web/dist/assets/{settings-menu-BAwHMXCR.js → settings-menu-D9fbi1Z0.js} +1 -1
- package/apps/web/dist/assets/ui-EuR3jezP.js +134 -0
- package/apps/web/dist/assets/{upload-DcAIMe8d.js → upload-BsMUhEfX.js} +1 -1
- package/apps/web/dist/index.html +3 -3
- package/apps/web/dist/mcp/flow.html +78 -78
- 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-Ck6_TSVJ.js +0 -1
- package/apps/web/dist/assets/ChatView-S1H9Pcih.js +0 -10
- package/apps/web/dist/assets/EditorPage-BSfJXx4W.js +0 -3
- package/apps/web/dist/assets/NewWizardPage-dumNiSqM.js +0 -7
- package/apps/web/dist/assets/OnboardingPage-BAfHLLNT.js +0 -1
- package/apps/web/dist/assets/ProjectPage-fneLQr6R.js +0 -1
- package/apps/web/dist/assets/PublicRunner-CuxDAXK7.js +0 -1
- package/apps/web/dist/assets/RunDrawer-C_T1I77g.js +0 -4
- package/apps/web/dist/assets/SettingsPage-DjFvKMRz.js +0 -1
- package/apps/web/dist/assets/SetupPage-CzYwVUvh.js +0 -1
- package/apps/web/dist/assets/index-CZFfDGHy.css +0 -1
- package/apps/web/dist/assets/index-DZTDv2pA.js +0 -14
- package/apps/web/dist/assets/ui-C5_NcAmG.js +0 -134
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { conditionMatches, conditionsOf, isDecidedField, isDecisionStep, isOtherwise, MODEL_CLASSES, } from "@engenty-wizards/shared/definition";
|
|
2
2
|
import { closedChoicesFor, openValue, otherwiseIndex, unavoidableFrom, unavoidableSteps, } from "@engenty-wizards/shared/fit";
|
|
3
|
-
import {
|
|
3
|
+
import { note, saidText } from "@engenty-wizards/shared/run";
|
|
4
4
|
import { classProblem, filmClient } from "../models.js";
|
|
5
5
|
// The steps every run passes through, and the choices that lead around a missing model, are
|
|
6
6
|
// pure and shared (packages/shared/src/fit.ts): the standalone check uses the same.
|
|
@@ -273,13 +273,12 @@ export function blockingMessage(missing) {
|
|
|
273
273
|
if (!blocking.length) {
|
|
274
274
|
return null;
|
|
275
275
|
}
|
|
276
|
-
|
|
277
|
-
.map((m) => {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
})
|
|
281
|
-
.
|
|
282
|
-
return bilingual(line("de"), line("en"));
|
|
276
|
+
return blocking
|
|
277
|
+
.map((m) => note("blockedSteps", {
|
|
278
|
+
steps: m.steps.map((s) => note("quoted", { text: s.title })),
|
|
279
|
+
problem: m.problem,
|
|
280
|
+
}))
|
|
281
|
+
.reduce((first, second) => note("joined", { first, second }));
|
|
283
282
|
}
|
|
284
283
|
/** The class a marketplace capability stands for; the rest need no model of their own. */
|
|
285
284
|
const CAPABILITY_CLASS = {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { marginOf, } from "@engenty-wizards/shared/decision";
|
|
2
2
|
import { branchValues, cardsFromData, conditionsOf, dataRef, followRules, formatsFor, isDecidedField, LIST_FORMATS, listRef, loopKey, MAX_SHOWN_FIELDS, optionsFromData, otherwiseOf, pageNeeds, whenHolds, wizardLang, } from "@engenty-wizards/shared/definition";
|
|
3
|
-
import {
|
|
3
|
+
import { note, saidText, } from "@engenty-wizards/shared/run";
|
|
4
4
|
import { CONVERSATION_RUNNERS, DEFAULT_RUNNER_SETTINGS } from "@engenty-wizards/shared/runners";
|
|
5
5
|
import { eq } from "drizzle-orm";
|
|
6
6
|
import { nanoid } from "nanoid";
|
|
@@ -43,7 +43,7 @@ export class RunInputError extends NotedError {
|
|
|
43
43
|
}
|
|
44
44
|
export class NoCreditsError extends NotedError {
|
|
45
45
|
constructor() {
|
|
46
|
-
super(
|
|
46
|
+
super(note("wizardRunOutCredits"));
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
/** The runs this process drives right now, with the handle that stops each. */
|
|
@@ -113,19 +113,19 @@ function friendly(err) {
|
|
|
113
113
|
}
|
|
114
114
|
// A runtime that runs alone pays its provider itself: its admin can top the account up.
|
|
115
115
|
if (!managed && /minimum balance|insufficient_funds|top up your credits/i.test(msg)) {
|
|
116
|
-
return
|
|
116
|
+
return note("providerCreditLow");
|
|
117
117
|
}
|
|
118
118
|
if (/rate.?limit|429/i.test(msg)) {
|
|
119
|
-
return
|
|
119
|
+
return note("aiServiceBusyRight");
|
|
120
120
|
}
|
|
121
121
|
if (/timeout|timed out/i.test(msg)) {
|
|
122
|
-
return
|
|
122
|
+
return note("stepTookTooLong");
|
|
123
123
|
}
|
|
124
124
|
// The platform's own provider account (budget, quota, key): nothing the person can fix.
|
|
125
125
|
if (/budget|quota|insufficient|billing|credit balance|api key|unauthori[sz]ed|401|403/i.test(msg)) {
|
|
126
|
-
return
|
|
126
|
+
return note("aiServiceNotReached");
|
|
127
127
|
}
|
|
128
|
-
return
|
|
128
|
+
return note("stepFailed", { detail: msg.slice(0, 300) });
|
|
129
129
|
}
|
|
130
130
|
/**
|
|
131
131
|
* A step that failed ends the run. A failure with a note (Apple Intelligence's) goes into the log
|
|
@@ -637,7 +637,7 @@ export async function submitPage(runId, stepId, input) {
|
|
|
637
637
|
(choice.values.length === 0 || choice.values.some((v) => String(v) === String(answer)))) {
|
|
638
638
|
errors.push({
|
|
639
639
|
field: id,
|
|
640
|
-
message:
|
|
640
|
+
message: note("notAvailableNow"),
|
|
641
641
|
});
|
|
642
642
|
}
|
|
643
643
|
}
|
|
@@ -653,9 +653,7 @@ export async function submitPage(runId, stepId, input) {
|
|
|
653
653
|
for (const id of Array.isArray(value) ? value : value ? [value] : []) {
|
|
654
654
|
const asset = await db.query.asset.findFirst({ where: eq(schema.asset.id, String(id)) });
|
|
655
655
|
if (asset?.runId !== runId) {
|
|
656
|
-
throw new RunInputError([
|
|
657
|
-
{ field: field.id, message: bilingual("Datei nicht gefunden", "File not found") },
|
|
658
|
-
]);
|
|
656
|
+
throw new RunInputError([{ field: field.id, message: note("fileNotFound") }]);
|
|
659
657
|
}
|
|
660
658
|
}
|
|
661
659
|
}
|
|
@@ -666,9 +664,7 @@ export async function submitPage(runId, stepId, input) {
|
|
|
666
664
|
values[field.id] = account.label;
|
|
667
665
|
}
|
|
668
666
|
else if (field.required) {
|
|
669
|
-
throw new RunInputError([
|
|
670
|
-
{ field: field.id, message: bilingual("Verbinde zuerst", "Connect first") },
|
|
671
|
-
]);
|
|
667
|
+
throw new RunInputError([{ field: field.id, message: note("connectFirst") }]);
|
|
672
668
|
}
|
|
673
669
|
}
|
|
674
670
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pOf } from "@engenty-wizards/shared/decision";
|
|
2
2
|
import { allFields, dataRef, isDecisionStep, LOCALES, templateRefs, wizardLang, } from "@engenty-wizards/shared/definition";
|
|
3
3
|
import { mainLogo, ruleLines } from "@engenty-wizards/shared/projects";
|
|
4
|
-
import {
|
|
4
|
+
import { note as runNote } from "@engenty-wizards/shared/run";
|
|
5
5
|
import { SURFACE_GUIDE, validateSurface, } from "@engenty-wizards/shared/surface";
|
|
6
6
|
import { Agent } from "@mastra/core/agent";
|
|
7
7
|
import { generateText, Output } from "ai";
|
|
@@ -379,7 +379,7 @@ function agentEntries(step, ctx) {
|
|
|
379
379
|
async function runAgentEach(step, ctx) {
|
|
380
380
|
const entries = agentEntries(step, ctx);
|
|
381
381
|
if (!entries.length) {
|
|
382
|
-
throw new StepError(
|
|
382
|
+
throw new StepError(runNote("noEntriesStepWork"));
|
|
383
383
|
}
|
|
384
384
|
// The view, if any, is composed once over the table of all entries.
|
|
385
385
|
const single = {
|
|
@@ -554,7 +554,7 @@ export async function runAgentStep(step, ctx) {
|
|
|
554
554
|
const text = step.output.format === "json" ? everything : closing || everything;
|
|
555
555
|
if (step.output.format !== "json") {
|
|
556
556
|
if (!text && !assets.length) {
|
|
557
|
-
throw new StepError(
|
|
557
|
+
throw new StepError(runNote("stepNotReturnResult"));
|
|
558
558
|
}
|
|
559
559
|
return { text, assets: assets.length ? assets : undefined, at: new Date().toISOString() };
|
|
560
560
|
}
|
|
@@ -755,7 +755,7 @@ async function writeHtml(step, ctx, kind) {
|
|
|
755
755
|
.replace(/```\s*$/, "")
|
|
756
756
|
.trim();
|
|
757
757
|
if (!/<html|<!doctype/i.test(html)) {
|
|
758
|
-
throw new StepError(
|
|
758
|
+
throw new StepError(runNote("documentNotCreated"));
|
|
759
759
|
}
|
|
760
760
|
// On screen (preview, PNG) a print document needs the margin its @page rule gives it on paper.
|
|
761
761
|
return kind === "document"
|
|
@@ -806,7 +806,7 @@ async function inParallel(items, limit, work) {
|
|
|
806
806
|
async function runMediaStep(step, ctx, asset) {
|
|
807
807
|
const entries = entriesOf(step, ctx);
|
|
808
808
|
if (!entries.length) {
|
|
809
|
-
throw new StepError(
|
|
809
|
+
throw new StepError(runNote("stepMissingSourcesImages"));
|
|
810
810
|
}
|
|
811
811
|
const previous = ctx.state.outputs[step.id];
|
|
812
812
|
const before = previous?.assets?.filter((a) => a.kind === asset) ?? [];
|
|
@@ -898,7 +898,7 @@ export async function runGenerateStep(step, ctx) {
|
|
|
898
898
|
case "voice": {
|
|
899
899
|
const text = renderTemplate(step.prompt, ctx.scope).trim().slice(0, 4000);
|
|
900
900
|
if (!text) {
|
|
901
|
-
throw new StepError(
|
|
901
|
+
throw new StepError(runNote("noTextReadAloud"));
|
|
902
902
|
}
|
|
903
903
|
const note = ctx.state.notes[step.id];
|
|
904
904
|
const media = await generateSpeechMedia({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { assembleSurface, dataRef, listRef, } from "@engenty-wizards/shared/definition";
|
|
2
|
-
import {
|
|
2
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
3
3
|
import { validateSurface } from "@engenty-wizards/shared/surface";
|
|
4
4
|
import { decide } from "./decide.js";
|
|
5
5
|
import { answersAsText, resolveRef } from "./template.js";
|
|
@@ -14,7 +14,7 @@ export async function runSurfaceStep(step, ctx) {
|
|
|
14
14
|
const components = step.components ?? (await decidedComponents(step, ctx));
|
|
15
15
|
const issues = validateSurface(components, Object.keys(data));
|
|
16
16
|
if (issues.length) {
|
|
17
|
-
throw new StepError(
|
|
17
|
+
throw new StepError(note("viewErrors", { detail: issues.map((i) => i.message).join(" ") }));
|
|
18
18
|
}
|
|
19
19
|
return { surface: { components, data }, at: new Date().toISOString() };
|
|
20
20
|
}
|
|
@@ -2,12 +2,12 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { readFile, rm, stat } from "node:fs/promises";
|
|
4
4
|
import { isAbsolute, join, normalize } from "node:path";
|
|
5
|
-
import {
|
|
5
|
+
import { note as runNote } from "@engenty-wizards/shared/run";
|
|
6
6
|
import { StepError } from "../engine/types.js";
|
|
7
7
|
import { CLAUDE_BIN, claudeEnv } from "../harness/claude.js";
|
|
8
8
|
import { failureOf } from "../harness/model.js";
|
|
9
9
|
import { openBridge } from "../mcp/bridge.js";
|
|
10
|
-
import {
|
|
10
|
+
import { saidOf } from "../model-errors.js";
|
|
11
11
|
import { filmClient } from "../models.js";
|
|
12
12
|
import { prepareFilmFolder, savedSession, saveSession } from "./project.js";
|
|
13
13
|
import { runHyperframes } from "./tools.js";
|
|
@@ -229,13 +229,13 @@ export async function runFilmStep(step, ctx) {
|
|
|
229
229
|
if (ctx.signal.aborted) {
|
|
230
230
|
throw err;
|
|
231
231
|
}
|
|
232
|
-
throw new StepError(
|
|
232
|
+
throw new StepError(runNote("filmClientStopped", { name: client.name, detail: err.message }));
|
|
233
233
|
});
|
|
234
234
|
const result = last;
|
|
235
235
|
if (!result || result.is_error) {
|
|
236
236
|
const detail = String(result?.result ?? (stderr.trim() || "no result")).slice(0, 400);
|
|
237
237
|
const failure = failureOf(client, detail);
|
|
238
|
-
throw new StepError(
|
|
238
|
+
throw new StepError(runNote("filmWorkSaved", { problem: saidOf(failure) }));
|
|
239
239
|
}
|
|
240
240
|
return result;
|
|
241
241
|
};
|
|
@@ -265,7 +265,7 @@ export async function runFilmStep(step, ctx) {
|
|
|
265
265
|
}
|
|
266
266
|
const problem = renderProblem(render.out);
|
|
267
267
|
if (attempt >= RENDER_FIXES) {
|
|
268
|
-
throw new StepError(
|
|
268
|
+
throw new StepError(runNote("filmRenderFailed", { detail: problem.slice(0, 400) }));
|
|
269
269
|
}
|
|
270
270
|
await ctx.emit("tool", { code: "filmFix" });
|
|
271
271
|
const fixed = await turn(`The final render of film/ failed:\n\n${problem}\n\nFind the cause in the composition's code, fix it, run \`check\` and a draft render through the hyperframes tool until both pass, and end with one line on what you fixed.`, await savedSession(root));
|
|
@@ -2,6 +2,7 @@ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { release } from "node:os";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { langOf, SPEECH_LOCALES } from "@engenty-wizards/shared/definition";
|
|
5
6
|
import { nanoid } from "nanoid";
|
|
6
7
|
import { env } from "../env.js";
|
|
7
8
|
import { ffmpeg, hasFfmpeg } from "../media/ffmpeg.js";
|
|
@@ -168,7 +169,7 @@ export function appleModel(alias) {
|
|
|
168
169
|
/** The Mac's own language: what a voice note is most likely in, unless the call names one. */
|
|
169
170
|
function systemLocale() {
|
|
170
171
|
const locale = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
171
|
-
return /^[a-z]{2}-[A-Z]{2}$/.test(locale) ? locale : locale
|
|
172
|
+
return /^[a-z]{2}-[A-Z]{2}$/.test(locale) ? locale : SPEECH_LOCALES[langOf(locale) ?? "en"];
|
|
172
173
|
}
|
|
173
174
|
/** What AVAudioFile reads as it is; a browser's WebM or Ogg (Opus) is turned into WAV first. */
|
|
174
175
|
function audioExtension(mediaType) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
2
2
|
import { resolveEnv, run } from "./env.js";
|
|
3
3
|
import { failureOf, HarnessModel, lastJson, runClient, } from "./model.js";
|
|
4
4
|
/**
|
|
@@ -143,5 +143,5 @@ export const claude = {
|
|
|
143
143
|
},
|
|
144
144
|
login: { args: ["auth", "login"], interactive: false },
|
|
145
145
|
model: (alias, effort) => new ClaudeCodeModel(claude, alias || "sonnet", effort),
|
|
146
|
-
exhausted:
|
|
146
|
+
exhausted: note("anthropicAccountClaudeCode"),
|
|
147
147
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
5
5
|
import { resolveEnv, run } from "./env.js";
|
|
6
6
|
import { failureOf, HarnessImageModel, HarnessModel, runClient, } from "./model.js";
|
|
7
7
|
/**
|
|
@@ -225,5 +225,5 @@ export const codex = {
|
|
|
225
225
|
login: { args: ["login"], interactive: false },
|
|
226
226
|
model: (alias, effort) => new CodexModel(codex, alias || "default", effort),
|
|
227
227
|
image: { alias: "image", model: (alias) => new CodexImageModel(codex, alias || "image") },
|
|
228
|
-
exhausted:
|
|
228
|
+
exhausted: note("chatgptAccountCodexSigned"),
|
|
229
229
|
};
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
5
5
|
import { nanoid } from "nanoid";
|
|
6
6
|
import { env } from "../env.js";
|
|
7
7
|
import { openBridge } from "../mcp/bridge.js";
|
|
8
8
|
import { ModelUnavailableError } from "../model-errors.js";
|
|
9
9
|
import { extensionOf, jsonInstruction, parseJsonAnswer, renderPrompt } from "./prompt.js";
|
|
10
10
|
const workDir = join(env.dataDir, "harness");
|
|
11
|
-
export const signedOut = (h) =>
|
|
12
|
-
export const notInstalled = (h) =>
|
|
13
|
-
export const exhausted = (h) => h.exhausted ??
|
|
14
|
-
bilingual(`Das Konto, mit dem ${h.name} angemeldet ist, hat kein Guthaben oder Kontingent mehr.`, `The account ${h.name} is signed in with has no credit or quota left.`);
|
|
11
|
+
export const signedOut = (h) => note("clientNotSignedIn", { name: h.name });
|
|
12
|
+
export const notInstalled = (h) => note("clientNotInstalled", { name: h.name });
|
|
13
|
+
export const exhausted = (h) => h.exhausted ?? note("clientNoCredit", { name: h.name });
|
|
15
14
|
/** The failure a client reports, as the person should read it. */
|
|
16
15
|
export function failureOf(h, detail) {
|
|
17
16
|
// The client's own words stay in the log: the sentence below sums them up for the person.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { accessSync, chmodSync, constants } from "node:fs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import { note } from "@engenty-wizards/shared/run";
|
|
5
5
|
import { nanoid } from "nanoid";
|
|
6
6
|
import { ServiceError } from "../services/errors.js";
|
|
7
7
|
const BUFFER = 200_000;
|
|
@@ -37,7 +37,7 @@ async function ptyModule() {
|
|
|
37
37
|
return { spawn };
|
|
38
38
|
}
|
|
39
39
|
catch {
|
|
40
|
-
throw new ServiceError("refused",
|
|
40
|
+
throw new ServiceError("refused", note("builtTerminalNotAvailable"));
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
function emit(session, event) {
|
|
@@ -85,7 +85,7 @@ export async function openTerminal(opts) {
|
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
catch (err) {
|
|
88
|
-
throw new ServiceError("refused",
|
|
88
|
+
throw new ServiceError("refused", note("commandNotStarted", { detail: err.message }));
|
|
89
89
|
}
|
|
90
90
|
const session = {
|
|
91
91
|
id,
|
|
@@ -147,7 +147,7 @@ export async function openTerminal(opts) {
|
|
|
147
147
|
function sessionOf(id) {
|
|
148
148
|
const session = sessions.get(id);
|
|
149
149
|
if (!session) {
|
|
150
|
-
throw new ServiceError("not_found",
|
|
150
|
+
throw new ServiceError("not_found", note("terminalNoLongerExists"));
|
|
151
151
|
}
|
|
152
152
|
return session;
|
|
153
153
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LANG_NAMES } from "@engenty-wizards/shared/definition";
|
|
1
2
|
import { NotedError } from "../model-errors.js";
|
|
2
3
|
import { conversationAccess } from "../models.js";
|
|
3
4
|
/**
|
|
@@ -10,8 +11,8 @@ const SECRETS_URL = "https://api.openai.com/v1/realtime/client_secrets";
|
|
|
10
11
|
const CALLS_URL = "https://api.openai.com/v1/realtime/calls";
|
|
11
12
|
/** How long a minted secret opens a session; the session itself goes on until it ends. */
|
|
12
13
|
const SECRET_TTL_SECONDS = 600;
|
|
13
|
-
/** The voice the wizard speaks with
|
|
14
|
-
const
|
|
14
|
+
/** The voice the wizard speaks with: one that speaks every language engenty does. */
|
|
15
|
+
const VOICE = "marin";
|
|
15
16
|
/** What the model may do: one tool per command of the run page, run by the browser. */
|
|
16
17
|
export const CONVERSATION_TOOLS = [
|
|
17
18
|
{
|
|
@@ -97,41 +98,23 @@ export const CONVERSATION_TOOLS = [
|
|
|
97
98
|
parameters: { type: "object", properties: {}, additionalProperties: false },
|
|
98
99
|
},
|
|
99
100
|
];
|
|
100
|
-
/** The rules the model speaks by
|
|
101
|
+
/** The rules the model speaks by: written in English, it speaks the wizard's language. */
|
|
101
102
|
export function conversationInstructions(view) {
|
|
102
|
-
const
|
|
103
|
-
const about = [
|
|
104
|
-
`${de ? "Du bist" : "You are"} ${view.wizard.title}.`,
|
|
105
|
-
view.wizard.description,
|
|
106
|
-
view.wizard.intro,
|
|
107
|
-
]
|
|
103
|
+
const about = [`You are ${view.wizard.title}.`, view.wizard.description, view.wizard.intro]
|
|
108
104
|
.filter(Boolean)
|
|
109
105
|
.join(" ");
|
|
110
|
-
const rules =
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
]
|
|
123
|
-
: [
|
|
124
|
-
"You hold a conversation that fills in a wizard step by step. The person also sees the wizard on the screen.",
|
|
125
|
-
"Speak English, short and friendly, as on the phone. One sentence, then the next question.",
|
|
126
|
-
"Ask one field at a time, in the order of the state. After each answer call set_field. When every field you can fill by voice is answered, call submit_page.",
|
|
127
|
-
"For a choice, name the options (at most four at a time) and pass exactly one of them on.",
|
|
128
|
-
"Read e-mail addresses, links and numbers back before passing them on.",
|
|
129
|
-
"A field that needs the screen (a photo, a file, a signature, a connection) is filled there by the person: say so in one sentence and wait for the next state.",
|
|
130
|
-
"While the wizard works, say in one sentence what it is doing and wait. Never make anything up.",
|
|
131
|
-
"At a review, sum the text up in a few words and ask whether it fits. Then accept_review, or regenerate with what the person wants changed.",
|
|
132
|
-
"At the end, say what was made and that it is on the screen.",
|
|
133
|
-
"With the camera on you can see what the person shows with look, and put a photo into a photo field with take_photo; ask for a photo field like this: 'Hold it to the camera, I will take the picture.' With the camera off, ask the person to switch it on, or leave the field to the screen.",
|
|
134
|
-
];
|
|
106
|
+
const rules = [
|
|
107
|
+
"You hold a conversation that fills in a wizard step by step. The person also sees the wizard on the screen.",
|
|
108
|
+
`Speak ${LANG_NAMES[view.lang]} (${view.lang}), short and friendly, as on the phone. One sentence, then the next question.`,
|
|
109
|
+
"Ask one field at a time, in the order of the state. After each answer call set_field. When every field you can fill by voice is answered, call submit_page.",
|
|
110
|
+
"For a choice, name the options (at most four at a time) and pass exactly one of them on.",
|
|
111
|
+
"Read e-mail addresses, links and numbers back before passing them on.",
|
|
112
|
+
"A field that needs the screen (a photo, a file, a signature, a connection) is filled there by the person: say so in one sentence and wait for the next state.",
|
|
113
|
+
"While the wizard works, say in one sentence what it is doing and wait. Never make anything up.",
|
|
114
|
+
"At a review, sum the text up in a few words and ask whether it fits. Then accept_review, or regenerate with what the person wants changed.",
|
|
115
|
+
"At the end, say what was made and that it is on the screen.",
|
|
116
|
+
"With the camera on you can see what the person shows with look, and put a photo into a photo field with take_photo; ask for a photo field like this: 'Hold it to the camera, I will take the picture.' With the camera off, ask the person to switch it on, or leave the field to the screen.",
|
|
117
|
+
];
|
|
135
118
|
return `${about}\n\n${rules.join("\n")}`;
|
|
136
119
|
}
|
|
137
120
|
/** Mints the secret a browser opens a session with; a failure carries a note for the run's language. */
|
|
@@ -157,7 +140,7 @@ export async function mintConversation(view) {
|
|
|
157
140
|
noise_reduction: { type: "far_field" },
|
|
158
141
|
turn_detection: { type: "server_vad", threshold: 0.7, silence_duration_ms: 600 },
|
|
159
142
|
},
|
|
160
|
-
output: { voice:
|
|
143
|
+
output: { voice: VOICE },
|
|
161
144
|
},
|
|
162
145
|
},
|
|
163
146
|
}),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { SPEECH_LOCALES } from "@engenty-wizards/shared/definition";
|
|
3
4
|
import { generateText, experimental_transcribe as transcribe } from "ai";
|
|
4
5
|
import { costOf, listenerModel, transcriptionCostUsd } from "../models.js";
|
|
5
6
|
import { ffmpeg, hasFfmpeg, probeMedia, withTempDir } from "./ffmpeg.js";
|
|
@@ -18,7 +19,7 @@ export async function transcribeAudio(input) {
|
|
|
18
19
|
audio: input.bytes,
|
|
19
20
|
abortSignal: input.abortSignal,
|
|
20
21
|
...(input.language
|
|
21
|
-
? { providerOptions: { apple: { locale: input.language
|
|
22
|
+
? { providerOptions: { apple: { locale: SPEECH_LOCALES[input.language] } } }
|
|
22
23
|
: {}),
|
|
23
24
|
});
|
|
24
25
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { noteText } from "@engenty-wizards/shared/run";
|
|
2
2
|
/**
|
|
3
|
-
* A failure the person reads, given as a note of `RUN_NOTES`
|
|
3
|
+
* A failure the person reads, given as a note of `RUN_NOTES` where it has
|
|
4
4
|
* one: a run shows it in the wizard's language, a response in the asker's, and the message keeps
|
|
5
5
|
* the English line for the log. Free text has no note.
|
|
6
6
|
*/
|