@gentbajko/slopify 2.0.2 → 2.1.0
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/SUBTITLES.md +1 -1
- package/dist/adapters/alignment/protocol.js +11 -1
- package/dist/adapters/alignment/runner.js +4 -1
- package/dist/adapters/alignment/threads.js +11 -0
- package/dist/adapters/alignment/worker.js +66 -9
- package/dist/adapters/explain.js +93 -0
- package/dist/adapters/ffmpeg.js +3 -3
- package/dist/adapters/host-cli/index.js +34 -3
- package/dist/adapters/host-cli/transport.js +4 -4
- package/dist/adapters/image/bytes.js +2 -2
- package/dist/adapters/image/codex-output.js +12 -12
- package/dist/adapters/image/codex.js +24 -8
- package/dist/adapters/image/fal.js +12 -6
- package/dist/adapters/image/google.js +18 -8
- package/dist/adapters/image/models.js +8 -2
- package/dist/adapters/image/openai.js +15 -6
- package/dist/adapters/image/replicate.js +16 -7
- package/dist/adapters/llm/claude-code-models.js +1 -1
- package/dist/adapters/llm/claude-code.js +16 -7
- package/dist/adapters/llm/cli-login-error.js +2 -1
- package/dist/adapters/llm/codex-models.js +1 -1
- package/dist/adapters/llm/codex.js +5 -6
- package/dist/adapters/llm/document-workspace.js +2 -2
- package/dist/adapters/llm/gemini-models.js +1 -1
- package/dist/adapters/llm/gemini-workspace.js +1 -1
- package/dist/adapters/llm/gemini.js +15 -11
- package/dist/adapters/llm/openrouter.js +21 -9
- package/dist/adapters/llm/run-cli.js +14 -11
- package/dist/adapters/tts/cartesia.js +10 -3
- package/dist/adapters/tts/elevenlabs.js +18 -6
- package/dist/adapters/tts/inworld-async.js +47 -16
- package/dist/adapters/tts/inworld.js +25 -15
- package/dist/adapters/tts/openai.js +18 -6
- package/dist/assets/document/SOURCE.txt +7 -0
- package/dist/assets/document/background.jpg +0 -0
- package/dist/assets/document/fonts/Cinzel-Black.ttf +0 -0
- package/dist/assets/document/fonts/Cinzel-Bold.ttf +0 -0
- package/dist/assets/document/fonts/Cinzel-Medium.ttf +0 -0
- package/dist/assets/document/fonts/Cinzel-Regular.ttf +0 -0
- package/dist/assets/document/fonts/OFL.txt +93 -0
- package/dist/assets/document/fonts/SOURCE.txt +11 -0
- package/dist/catalog/registry.js +13 -10
- package/dist/catalog/store.js +1 -1
- package/dist/catalog/validate.js +16 -6
- package/dist/edge/cli.js +33 -7
- package/dist/edge/docker-launch.js +6 -6
- package/dist/edge/docker-projects/engine.js +34 -13
- package/dist/edge/docker-projects/install.js +8 -8
- package/dist/edge/docker-projects/state.js +11 -7
- package/dist/edge/docker-projects/tree.js +6 -6
- package/dist/edge/docker.js +13 -13
- package/dist/edge/host-cli.js +14 -0
- package/dist/edge/http/actions.js +27 -25
- package/dist/edge/http/app.js +3 -3
- package/dist/edge/http/audio-preview.js +1 -1
- package/dist/edge/http/checkpoints.js +5 -1
- package/dist/edge/http/diagnostics.js +3 -1
- package/dist/edge/http/draft-files.js +2 -2
- package/dist/edge/http/draft-problem.js +11 -1
- package/dist/edge/http/files.js +4 -4
- package/dist/edge/http/folder-location-schema.js +5 -8
- package/dist/edge/http/folder-location.js +13 -8
- package/dist/edge/http/fonts.js +22 -10
- package/dist/edge/http/host-cli.js +61 -14
- package/dist/edge/http/multipart.js +7 -5
- package/dist/edge/http/open-folder.js +2 -2
- package/dist/edge/http/planning.js +4 -4
- package/dist/edge/http/problem.js +2 -2
- package/dist/edge/http/project-templates.js +7 -3
- package/dist/edge/http/projects.js +8 -8
- package/dist/edge/http/prompts.js +9 -4
- package/dist/edge/http/providers.js +15 -7
- package/dist/edge/http/revision-files.js +8 -4
- package/dist/edge/http/revisions.js +30 -4
- package/dist/edge/http/schedules.js +9 -9
- package/dist/edge/http/settings.js +15 -9
- package/dist/edge/http/staging.js +5 -5
- package/dist/edge/http/storage.js +4 -4
- package/dist/edge/http/subtitles.js +1 -1
- package/dist/edge/http/tutorial.js +2 -2
- package/dist/edge/http/update.js +3 -3
- package/dist/host-cli/install.js +28 -6
- package/dist/host-cli/open-folder.js +95 -0
- package/dist/host-cli/paths.js +6 -6
- package/dist/host-cli/runtime.js +2 -0
- package/dist/host-cli/server.js +1 -1
- package/dist/host-cli/service.js +11 -11
- package/dist/host-cli/status.js +7 -3
- package/dist/kernel/config/index.js +6 -4
- package/dist/kernel/db/migrate.js +27 -2
- package/dist/kernel/db/migrations/0013-schedule-topic-queue.sql +4 -0
- package/dist/kernel/db/migrations/0014-document-stage.sql +44 -0
- package/dist/kernel/db/migrations/0015-description-prompts.sql +13 -0
- package/dist/kernel/lock.js +4 -3
- package/dist/kernel/pipeline.js +11 -1
- package/dist/kernel/ports/host-cli.js +14 -0
- package/dist/kernel/ports/subtitles.js +15 -1
- package/dist/kernel/runner/attempt.js +26 -2
- package/dist/kernel/runner/graph.js +6 -1
- package/dist/main.js +8 -4
- package/dist/slices/admission/model.js +7 -1
- package/dist/slices/admission/rules.js +98 -22
- package/dist/slices/admission/schema.js +16 -3
- package/dist/slices/admission/start.js +3 -2
- package/dist/slices/article/continuation.js +4 -2
- package/dist/slices/article/plain.js +2 -2
- package/dist/slices/article/provided-entries.js +3 -3
- package/dist/slices/article/run.js +2 -2
- package/dist/slices/article/segments.js +5 -3
- package/dist/slices/control/providers.js +20 -7
- package/dist/slices/document/blocks.js +129 -0
- package/dist/slices/document/flow.js +117 -0
- package/dist/slices/document/fonts.js +54 -0
- package/dist/slices/document/model.js +11 -0
- package/dist/slices/document/pages.js +198 -0
- package/dist/slices/document/render.js +242 -0
- package/dist/slices/document/sources.js +35 -0
- package/dist/slices/document/theme.js +158 -0
- package/dist/slices/document/writer.js +66 -0
- package/dist/slices/estimate/index.js +14 -2
- package/dist/slices/fonts/catalog.js +1 -1
- package/dist/slices/fonts/upload.js +1 -1
- package/dist/slices/images/run.js +5 -5
- package/dist/slices/library/lint.js +13 -7
- package/dist/slices/library/model.js +1 -1
- package/dist/slices/library/slots.js +6 -3
- package/dist/slices/narration/concat.js +1 -1
- package/dist/slices/narration/pronunciation-chunks.js +3 -3
- package/dist/slices/narration/pronunciation.js +2 -2
- package/dist/slices/narration/run.js +7 -7
- package/dist/slices/narration/steering.js +3 -3
- package/dist/slices/play-drafts/convert.js +35 -5
- package/dist/slices/play-drafts/readiness.js +15 -8
- package/dist/slices/play-drafts/review-inputs.js +7 -4
- package/dist/slices/play-drafts/review.js +3 -3
- package/dist/slices/play-drafts/schema.js +22 -5
- package/dist/slices/play-drafts/service.js +3 -1
- package/dist/slices/play-drafts/uploads.js +1 -1
- package/dist/slices/project-templates/from-project.js +10 -0
- package/dist/slices/project-templates/setup.js +1 -0
- package/dist/slices/rebuild/admission-repo.js +2 -2
- package/dist/slices/rebuild/preview-details.js +11 -1
- package/dist/slices/rebuild/recipe-audio.js +3 -0
- package/dist/slices/rebuild/recipe-build.js +6 -1
- package/dist/slices/rebuild/recipe-document.js +36 -0
- package/dist/slices/rebuild/recipe-exports.js +14 -2
- package/dist/slices/rebuild/recipe-fixture.js +4 -0
- package/dist/slices/rebuild/recipe-legacy.js +6 -1
- package/dist/slices/rebuild/recipe-model.js +2 -0
- package/dist/slices/rebuild/recipe-narration-text.js +1 -1
- package/dist/slices/rebuild/recipe-provider-choice.js +3 -0
- package/dist/slices/rebuild/recipe-save.js +15 -3
- package/dist/slices/rebuild/recipe-validation.js +15 -2
- package/dist/slices/rebuild/recipe-visual.js +11 -2
- package/dist/slices/rebuild/recipe-work.js +15 -0
- package/dist/slices/rebuild/recipe-youtube.js +33 -0
- package/dist/slices/rebuild/recovery-selection.js +2 -0
- package/dist/slices/rebuild/recovery.js +12 -7
- package/dist/slices/rebuild/repo.js +3 -3
- package/dist/slices/rebuild/runtime-actions.js +2 -0
- package/dist/slices/rebuild/runtime-admission.js +4 -4
- package/dist/slices/rebuild/runtime-article.js +5 -5
- package/dist/slices/rebuild/runtime-checkpoints.js +4 -4
- package/dist/slices/rebuild/runtime-document.js +85 -0
- package/dist/slices/rebuild/runtime-export-inputs.js +7 -6
- package/dist/slices/rebuild/runtime-export.js +39 -23
- package/dist/slices/rebuild/runtime-local.js +6 -6
- package/dist/slices/rebuild/runtime-narration-text.js +46 -7
- package/dist/slices/rebuild/runtime-piece-label.js +66 -0
- package/dist/slices/rebuild/runtime-provider.js +6 -4
- package/dist/slices/rebuild/runtime-publication.js +4 -3
- package/dist/slices/rebuild/runtime-run.js +22 -4
- package/dist/slices/rebuild/runtime-store.js +7 -2
- package/dist/slices/rebuild/runtime-subtitles.js +82 -16
- package/dist/slices/rebuild/runtime-youtube.js +84 -0
- package/dist/slices/rebuild/transition-repo.js +8 -6
- package/dist/slices/reruns/cascade.js +6 -4
- package/dist/slices/reruns/index.js +1 -1
- package/dist/slices/research/run.js +9 -7
- package/dist/slices/research/synthesis.js +4 -2
- package/dist/slices/revisions/mutation-assets.js +26 -8
- package/dist/slices/revisions/mutation-cues.js +4 -2
- package/dist/slices/revisions/projection.js +2 -1
- package/dist/slices/revisions/rules.js +18 -9
- package/dist/slices/revisions/schema.js +1 -1
- package/dist/slices/schedules/repo.js +55 -11
- package/dist/slices/schedules/scheduler.js +25 -8
- package/dist/slices/schedules/schema.js +19 -4
- package/dist/slices/schedules/service.js +2 -0
- package/dist/slices/settings/cli-paths.js +7 -4
- package/dist/slices/settings/models.js +4 -4
- package/dist/slices/settings/playback.js +2 -2
- package/dist/slices/storage/assets.js +5 -5
- package/dist/slices/storage/downloads.js +1 -0
- package/dist/slices/storage/layout.js +7 -1
- package/dist/slices/storage/model.js +3 -0
- package/dist/slices/subtitles/captions.js +1 -1
- package/dist/slices/subtitles/prepare.js +7 -6
- package/dist/slices/subtitles/transcript.js +1 -1
- package/dist/slices/telemetry/model.js +1 -1
- package/dist/slices/thumbnail/run.js +8 -8
- package/dist/slices/video/audio-export.js +11 -3
- package/dist/slices/video/audio-inputs.js +2 -2
- package/dist/slices/video/edit-list.js +73 -0
- package/dist/slices/video/ffmpeg.js +129 -61
- package/dist/slices/video/motion.js +51 -0
- package/dist/slices/video/plan.js +62 -28
- package/dist/slices/video/reuse-audio.js +2 -0
- package/dist/slices/video/run.js +23 -12
- package/dist/slices/video/slideshow.js +48 -0
- package/dist/slices/video/write-export.js +17 -25
- package/dist/slices/youtube/answer.js +199 -0
- package/dist/slices/youtube/model.js +27 -0
- package/dist/slices/youtube/timestamps.js +24 -0
- package/dist/slices/youtube/transcript.js +47 -0
- package/dist/updater/plan.js +1 -1
- package/dist/updater/service.js +4 -3
- package/dist/updater/worker.js +6 -4
- package/dist/web/assets/index-B6NbhpjD.css +1 -0
- package/dist/web/assets/index-ComF5gwP.js +142 -0
- package/dist/web/index.html +2 -2
- package/package.json +4 -2
- package/dist/web/assets/index-CZNiHm8P.css +0 -1
- package/dist/web/assets/index-DPgGLX5m.js +0 -137
package/dist/edge/docker.js
CHANGED
|
@@ -5,13 +5,13 @@ import { z } from "zod";
|
|
|
5
5
|
import { installHostPackage } from "../host-cli/install.js";
|
|
6
6
|
import { ensureBridgeToken, hasCode, prepareHostPaths } from "../host-cli/paths.js";
|
|
7
7
|
import { ensureHostService, privateRead, privateWrite } from "../host-cli/service.js";
|
|
8
|
-
import { resolveHostCommand } from "../host-cli/status.js";
|
|
8
|
+
import { hostCommandName, resolveHostCommand } from "../host-cli/status.js";
|
|
9
9
|
import { hostCliProtocol, hostLlmIds } from "../kernel/ports/host-cli.js";
|
|
10
10
|
export function assertManagedDockerHost(platform, uid, gid) {
|
|
11
11
|
if (platform !== "linux")
|
|
12
|
-
throw new Error("The
|
|
12
|
+
throw new Error("The --docker launcher only works on Linux. On this system, run Slopify without Docker (npx @gentbajko/slopify), or start the Slopify Docker image yourself with docker run.");
|
|
13
13
|
if (uid === undefined || gid === undefined || uid === 0)
|
|
14
|
-
throw new Error("
|
|
14
|
+
throw new Error("Don't run the --docker launcher with sudo or as root. Run it as your normal user, and if Docker then says permission denied, give your user access: sudo usermod -aG docker $USER, then log out and back in.");
|
|
15
15
|
}
|
|
16
16
|
export async function prepareDockerHostCli(options) {
|
|
17
17
|
if (options.disabled)
|
|
@@ -24,16 +24,16 @@ export async function prepareDockerHostCli(options) {
|
|
|
24
24
|
}
|
|
25
25
|
catch (error) {
|
|
26
26
|
if (!hasCode(error, "ENOENT"))
|
|
27
|
-
throw new Error(
|
|
27
|
+
throw new Error(`Could not check whether ${hostCommandName(id)} is installed on this machine (${error instanceof Error ? error.message : String(error)}). Nothing was changed. Fix the problem, or start with --host-cli=off to use API keys only.`);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
if (!installed)
|
|
31
31
|
return {};
|
|
32
32
|
if (process.platform !== "linux")
|
|
33
|
-
throw new Error("
|
|
33
|
+
throw new Error("Using this machine's AI CLIs from Docker needs Linux with systemd. Start with --host-cli=off to use API keys only.");
|
|
34
34
|
const uid = process.getuid?.();
|
|
35
35
|
if (uid === undefined || uid === 0)
|
|
36
|
-
throw new Error("
|
|
36
|
+
throw new Error("Don't run the --docker launcher with sudo or as root; run it as your normal user. Or start with --host-cli=off to use API keys only.");
|
|
37
37
|
const receiptPath = join(options.root, "consent.json");
|
|
38
38
|
const existing = await privateRead(receiptPath, uid);
|
|
39
39
|
const receipt = z.object({ version: z.literal(1), automaticStartup: z.literal(true) }).strict();
|
|
@@ -43,15 +43,15 @@ export async function prepareDockerHostCli(options) {
|
|
|
43
43
|
approved ||= receipt.safeParse(JSON.parse(existing)).success;
|
|
44
44
|
}
|
|
45
45
|
catch {
|
|
46
|
-
throw new Error(
|
|
46
|
+
throw new Error(`The saved answer to the host CLI question (${receiptPath}) is damaged. Delete that file and run the launcher again to be asked again.`);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
if (!approved) {
|
|
50
50
|
if (!options.interactive)
|
|
51
|
-
throw new Error("
|
|
51
|
+
throw new Error("Slopify needs your OK to use the Claude Code, Codex or Gemini CLI installed on this machine, but can't ask because this isn't an interactive terminal. Rerun with --accept-host-cli to allow it, or with --host-cli=off to use API keys only.");
|
|
52
52
|
approved = await options.prompt("Allow Slopify to run your host Claude Code, Codex and Gemini CLIs using their existing logins? This installs a private helper and enables automatic startup. User lingering keeps your user services running after logout and at boot. Credentials stay on the host. [y/N] ");
|
|
53
53
|
if (!approved)
|
|
54
|
-
throw new Error("
|
|
54
|
+
throw new Error("You declined, so Slopify did not set up your host AI CLIs and nothing was changed. Run the launcher again and answer y to allow it, or add --host-cli=off to start with API keys only.");
|
|
55
55
|
}
|
|
56
56
|
const inspect = () => options.runner.exec("docker", [
|
|
57
57
|
"image",
|
|
@@ -64,14 +64,14 @@ export async function prepareDockerHostCli(options) {
|
|
|
64
64
|
if (image.code !== 0 || image.stdout.trim() !== String(hostCliProtocol)) {
|
|
65
65
|
const pulled = await options.runner.exec("docker", ["pull", options.image], options.signal);
|
|
66
66
|
if (pulled.code !== 0)
|
|
67
|
-
throw new Error(
|
|
67
|
+
throw new Error(`Could not download the Slopify Docker image ${options.image}. Check your internet connection and that Docker is running (docker info), then try again. Nothing was changed.`);
|
|
68
68
|
image = await inspect();
|
|
69
69
|
if (image.code !== 0 || image.stdout.trim() !== String(hostCliProtocol))
|
|
70
|
-
throw new Error(
|
|
70
|
+
throw new Error(`The Docker image ${options.image} is too old to use the AI CLIs on this machine. Use the latest image (unset SLOPIFY_DOCKER_IMAGE, or point it to a current release) and try again, or start with --host-cli=off.`);
|
|
71
71
|
}
|
|
72
72
|
const supported = await options.runner.exec("systemctl", ["--user", "list-units", "--no-legend", "--no-pager", "slopify-cli-bridge.service"], options.signal);
|
|
73
73
|
if (supported.code !== 0)
|
|
74
|
-
throw new Error("
|
|
74
|
+
throw new Error("Using this machine's AI CLIs from Docker needs systemd user services (systemctl --user), which aren't available here. Start with --host-cli=off to use API keys only, or run Slopify without Docker: npx @gentbajko/slopify.");
|
|
75
75
|
const paths = await prepareHostPaths(options.root);
|
|
76
76
|
const lock = join(paths.root, "setup.lock");
|
|
77
77
|
const deadline = Date.now() + 30_000;
|
|
@@ -84,7 +84,7 @@ export async function prepareDockerHostCli(options) {
|
|
|
84
84
|
if (!hasCode(error, "EEXIST"))
|
|
85
85
|
throw error;
|
|
86
86
|
if (Date.now() >= deadline)
|
|
87
|
-
throw new Error(
|
|
87
|
+
throw new Error(`Another Slopify launcher is setting up the host CLI helper right now. Wait for it to finish and try again. If no other launcher is running, delete the folder ${lock} and retry.`);
|
|
88
88
|
await delay(100, undefined, { signal: options.signal });
|
|
89
89
|
}
|
|
90
90
|
}
|
package/dist/edge/host-cli.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { constants } from "node:fs";
|
|
2
2
|
import { open } from "node:fs/promises";
|
|
3
|
+
import { homedir } from "node:os";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { parseArgs } from "node:util";
|
|
5
6
|
import { nodeRunCli } from "../adapters/llm/run-cli.js";
|
|
6
7
|
import { hostEnvironmentSchema } from "../host-cli/environment.js";
|
|
8
|
+
import { launchXdgOpen } from "../host-cli/open-folder.js";
|
|
7
9
|
import { ensureBridgeToken, prepareHostPaths } from "../host-cli/paths.js";
|
|
8
10
|
import { createHostRuntime } from "../host-cli/runtime.js";
|
|
9
11
|
import { startHostServer } from "../host-cli/server.js";
|
|
10
12
|
import { resolveHostCommand } from "../host-cli/status.js";
|
|
11
13
|
import { readVersion } from "../kernel/version.js";
|
|
12
14
|
import { nodeCliProbe } from "../slices/settings/cli-status.js";
|
|
15
|
+
import { dockerRoot } from "./docker-projects/state.js";
|
|
13
16
|
const { values } = parseArgs({ options: { "state-dir": { type: "string" } }, strict: true });
|
|
14
17
|
if (!values["state-dir"])
|
|
15
18
|
throw new Error("A host helper state directory is required.");
|
|
@@ -32,6 +35,14 @@ try {
|
|
|
32
35
|
finally {
|
|
33
36
|
await file.close();
|
|
34
37
|
}
|
|
38
|
+
// Without a usable data folder there are no launcher receipts, so Open folder stays unsupported.
|
|
39
|
+
let folderRoot;
|
|
40
|
+
try {
|
|
41
|
+
folderRoot = dockerRoot(process.env, process.env.HOME || homedir());
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
folderRoot = undefined;
|
|
45
|
+
}
|
|
35
46
|
const server = await startHostServer({
|
|
36
47
|
directory: paths.share,
|
|
37
48
|
token: await ensureBridgeToken(paths.tokenFile),
|
|
@@ -42,6 +53,9 @@ const server = await startHostServer({
|
|
|
42
53
|
env: process.env,
|
|
43
54
|
now: Date.now,
|
|
44
55
|
resolve: (id) => resolveHostCommand(id, process.env),
|
|
56
|
+
...(process.getuid === undefined || folderRoot === undefined
|
|
57
|
+
? {}
|
|
58
|
+
: { folders: { root: folderRoot, uid: process.getuid(), launch: launchXdgOpen } }),
|
|
45
59
|
}),
|
|
46
60
|
});
|
|
47
61
|
process.on("SIGHUP", server.pauseAdmissions);
|
|
@@ -91,15 +91,15 @@ export function actionRoutes(deps) {
|
|
|
91
91
|
"rebuild-required": 409,
|
|
92
92
|
};
|
|
93
93
|
const messages = {
|
|
94
|
-
"no-project": "
|
|
95
|
-
running: "Pause
|
|
96
|
-
"not-editable": "Providers can be changed only while
|
|
97
|
-
"invalid-providers": "
|
|
98
|
-
"catalog-unavailable": "
|
|
99
|
-
"revision-required": "
|
|
100
|
-
conflict: "
|
|
101
|
-
"idempotency-conflict": "This
|
|
102
|
-
"rebuild-required": "
|
|
94
|
+
"no-project": "This project no longer exists. Go back to Projects to pick another.",
|
|
95
|
+
running: "This project is still running. Pause it and wait for the current step to stop before changing providers.",
|
|
96
|
+
"not-editable": "Providers can be changed only while the project is paused or has failed. Pause it first, then try again.",
|
|
97
|
+
"invalid-providers": "Some provider choices are not valid. Fix the highlighted fields and try again.",
|
|
98
|
+
"catalog-unavailable": "Slopify could not load the list of available models. Wait a moment and try again; if it keeps failing, check Settings → Models.",
|
|
99
|
+
"revision-required": "This page is out of date. Reload the page, then try again.",
|
|
100
|
+
conflict: "This project changed since the page loaded. Reload the page to see the latest, then try again.",
|
|
101
|
+
"idempotency-conflict": "This action was already sent with different details. Reload the page, then try again.",
|
|
102
|
+
"rebuild-required": "This change needs some outputs to be made again. In the Edit tab, use Rebuild affected outputs to see what will be regenerated and what it costs.",
|
|
103
103
|
};
|
|
104
104
|
return problem(c, {
|
|
105
105
|
status: codes[result.reason],
|
|
@@ -117,7 +117,7 @@ export function actionRoutes(deps) {
|
|
|
117
117
|
return problem(c, {
|
|
118
118
|
status: 503,
|
|
119
119
|
title: titleOf(503),
|
|
120
|
-
detail: "
|
|
120
|
+
detail: "Resume and retry are not ready yet because Slopify is still starting. Wait a moment, reload the page and try again.",
|
|
121
121
|
});
|
|
122
122
|
const result = recoveryResultSchema.parse(await recoverProject(deps.rebuild, id, { ...input, action }));
|
|
123
123
|
if (result.ok)
|
|
@@ -128,26 +128,28 @@ export function actionRoutes(deps) {
|
|
|
128
128
|
? 400
|
|
129
129
|
: 409;
|
|
130
130
|
const messages = {
|
|
131
|
-
"no-project": "This project no longer exists.",
|
|
132
|
-
"no-revision": "
|
|
133
|
-
conflict: "
|
|
134
|
-
"idempotency-conflict": "This
|
|
135
|
-
"invalid-edit": "This section
|
|
136
|
-
"stale-preview": "
|
|
137
|
-
"invalid-selection": "This section has
|
|
138
|
-
"review-required": "
|
|
139
|
-
"cost-ack-required": "
|
|
140
|
-
readiness: "Check the provider, model, voice
|
|
141
|
-
running: "Wait for
|
|
142
|
-
"accepted-job": "This section
|
|
143
|
-
"control-changed": "
|
|
131
|
+
"no-project": "This project no longer exists. Go back to Projects to pick another.",
|
|
132
|
+
"no-revision": "The project's saved settings changed since the page loaded. Reload the page, then try again.",
|
|
133
|
+
conflict: "This project changed since the page loaded. Reload the page to see the latest, then use Resume again.",
|
|
134
|
+
"idempotency-conflict": "This action was already sent with different details. Reload the page, then try again.",
|
|
135
|
+
"invalid-edit": "This section has settings that need fixing first. Open the Edit tab, choose Edit project and correct this section, then try again.",
|
|
136
|
+
"stale-preview": "What needs to be made changed since the page loaded. Reload the page, then use Resume again.",
|
|
137
|
+
"invalid-selection": "This section has nothing generated to re-run because its content was supplied by you. To change it, open the Edit tab and choose Edit project.",
|
|
138
|
+
"review-required": "Content you supplied or captions you edited by hand would be replaced. Change them in the Edit tab with Edit project, or use Rebuild affected outputs to confirm the replacement.",
|
|
139
|
+
"cost-ack-required": "This re-run needs you to review its cost first. In the Edit tab, use Rebuild affected outputs.",
|
|
140
|
+
readiness: "Slopify cannot run this yet. Check the provider, model, voice and any files you supplied, then use Resume.",
|
|
141
|
+
running: "This section is still running. Wait for it to finish, or Pause the project, before re-running it.",
|
|
142
|
+
"accepted-job": "This section has a finished provider job that Slopify has not collected yet.",
|
|
143
|
+
"control-changed": "Another action on this project (such as Pause or Cancel) happened at the same time. Reload the page to see its current state, then try again.",
|
|
144
144
|
};
|
|
145
145
|
const detail = [
|
|
146
146
|
messages[result.reason],
|
|
147
147
|
...(result.fields ?? []).map((row) => row.message),
|
|
148
148
|
...(result.intentRevisionId === undefined
|
|
149
149
|
? []
|
|
150
|
-
: [
|
|
150
|
+
: [
|
|
151
|
+
"Your re-run request was saved. Use Resume to continue it instead of re-running again.",
|
|
152
|
+
]),
|
|
151
153
|
].join(" ");
|
|
152
154
|
return problem(c, {
|
|
153
155
|
status,
|
|
@@ -218,7 +220,7 @@ function revisionRequired(c) {
|
|
|
218
220
|
return problem(c, {
|
|
219
221
|
status: 409,
|
|
220
222
|
title: titleOf(409),
|
|
221
|
-
detail: "
|
|
223
|
+
detail: "This change is now made from the Edit tab. Choose Edit project, save your change, then use Rebuild affected outputs.",
|
|
222
224
|
extensions: { reason: "revision-required" },
|
|
223
225
|
});
|
|
224
226
|
}
|
package/dist/edge/http/app.js
CHANGED
|
@@ -80,14 +80,14 @@ export function createApp(deps) {
|
|
|
80
80
|
return problem(c, {
|
|
81
81
|
status: 503,
|
|
82
82
|
title: titleOf(503),
|
|
83
|
-
detail: "
|
|
83
|
+
detail: "Slopify is still finishing its Docker setup. Wait for the launcher to finish, then try again.",
|
|
84
84
|
});
|
|
85
85
|
const releaseRequest = deps.mutations?.begin();
|
|
86
86
|
if (deps.mutations !== undefined && releaseRequest === undefined)
|
|
87
87
|
return problem(c, {
|
|
88
88
|
status: 503,
|
|
89
89
|
title: titleOf(503),
|
|
90
|
-
detail: "Slopify is shutting down.
|
|
90
|
+
detail: "Slopify is shutting down, so changes cannot be saved right now. Start it again, reload the page and try again.",
|
|
91
91
|
});
|
|
92
92
|
const updateRoute = [
|
|
93
93
|
"/api/update",
|
|
@@ -101,7 +101,7 @@ export function createApp(deps) {
|
|
|
101
101
|
return problem(c, {
|
|
102
102
|
status: 409,
|
|
103
103
|
title: titleOf(409),
|
|
104
|
-
detail: "Slopify is updating. Wait for it to restart
|
|
104
|
+
detail: "Slopify is updating. Wait for it to restart, reload the page and try again.",
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
107
|
try {
|
|
@@ -49,6 +49,6 @@ function missing(c) {
|
|
|
49
49
|
return problem(c, {
|
|
50
50
|
status: 404,
|
|
51
51
|
title: titleOf(404),
|
|
52
|
-
detail: "This live audio preview
|
|
52
|
+
detail: "This live audio preview has ended. Play the finished narration from the project's audio outputs instead.",
|
|
53
53
|
});
|
|
54
54
|
}
|
|
@@ -20,7 +20,11 @@ function refused(c, reason) {
|
|
|
20
20
|
return problem(c, {
|
|
21
21
|
status,
|
|
22
22
|
title: titleOf(status),
|
|
23
|
-
detail:
|
|
23
|
+
detail: reason === "not-found"
|
|
24
|
+
? "This checkpoint no longer exists; the project may have moved on or changed. Reload the page to see where it is now."
|
|
25
|
+
: reason === "invalid-input"
|
|
26
|
+
? "This checkpoint answer could not be read. Reload the page and try again."
|
|
27
|
+
: "This checkpoint changed since the page loaded, for example it was already approved. Reload the page to see its current state, then try again.",
|
|
24
28
|
extensions: { reason },
|
|
25
29
|
});
|
|
26
30
|
}
|
|
@@ -29,7 +29,9 @@ export function diagnosticsRoutes(deps) {
|
|
|
29
29
|
...(provider.cliPath === undefined ? {} : { cliPath: provider.cliPath }),
|
|
30
30
|
})),
|
|
31
31
|
projects: { total: typeof projectCount?.count === "number" ? projectCount.count : 0 },
|
|
32
|
-
catalogue: deps.catalogue?.status() ?? {
|
|
32
|
+
catalogue: deps.catalogue?.status() ?? {
|
|
33
|
+
warning: "The model list (models.yaml) is not loaded yet. Wait a moment and reload the page; if it stays like this, restart Slopify.",
|
|
34
|
+
},
|
|
33
35
|
});
|
|
34
36
|
});
|
|
35
37
|
}
|
|
@@ -32,7 +32,7 @@ export function draftFileRoutes(service) {
|
|
|
32
32
|
return problem(c, {
|
|
33
33
|
status: 400,
|
|
34
34
|
title: titleOf(400),
|
|
35
|
-
detail: "
|
|
35
|
+
detail: "No file arrived with the upload. Choose the file again and retry.",
|
|
36
36
|
});
|
|
37
37
|
return result.ok
|
|
38
38
|
? c.json(draftAttachmentSchema.parse(result.value))
|
|
@@ -57,7 +57,7 @@ export function draftFileRoutes(service) {
|
|
|
57
57
|
return problem(c, {
|
|
58
58
|
status: 404,
|
|
59
59
|
title: titleOf(404),
|
|
60
|
-
detail: "This
|
|
60
|
+
detail: "This attached file has not finished uploading, so it cannot be previewed yet. Wait a moment or attach it again.",
|
|
61
61
|
});
|
|
62
62
|
return c.body(Readable.toWeb(createReadStream(stagingPath(deps.paths, staged.path))), 200, {
|
|
63
63
|
"content-type": contentType,
|
|
@@ -6,10 +6,20 @@ export function draftProblem(c, result) {
|
|
|
6
6
|
? 400
|
|
7
7
|
: 409;
|
|
8
8
|
const { ok: _ok, ...extensions } = result;
|
|
9
|
+
const details = {
|
|
10
|
+
"not-found": "This draft no longer exists; it may have been started or deleted. Reload the page to start a new one.",
|
|
11
|
+
"invalid-draft": "This saved draft could not be read. Reload the page and set the video up again in Play.",
|
|
12
|
+
conflict: "This draft changed in another tab or window. Reload the page to see the latest, then make your change again.",
|
|
13
|
+
"invalid-edit": "Some settings need fixing. Fix the highlighted fields, then try again.",
|
|
14
|
+
"pending-start": "This video is already starting. Wait a moment, then find it in Projects.",
|
|
15
|
+
"already-started": "This draft was already started. Find the video in Projects.",
|
|
16
|
+
"stale-review": "Something changed since you reviewed this video, such as a setting or a price. Choose Review and start again to see the latest.",
|
|
17
|
+
readiness: "Slopify is not ready to start this video yet. Fix the highlighted problems, then try again.",
|
|
18
|
+
};
|
|
9
19
|
return problem(c, {
|
|
10
20
|
status,
|
|
11
21
|
title: titleOf(status),
|
|
12
|
-
detail:
|
|
22
|
+
detail: details[result.reason],
|
|
13
23
|
extensions,
|
|
14
24
|
});
|
|
15
25
|
}
|
package/dist/edge/http/files.js
CHANGED
|
@@ -58,10 +58,10 @@ function disposition(filename) {
|
|
|
58
58
|
}
|
|
59
59
|
function missing(c, reason) {
|
|
60
60
|
const details = {
|
|
61
|
-
"unknown-project": "
|
|
62
|
-
"unknown-asset": "This project has no
|
|
63
|
-
"missing-file": "This file
|
|
64
|
-
"no-images": "This project has no images or thumbnail yet.",
|
|
61
|
+
"unknown-project": "This project no longer exists. Go back to Projects to pick another.",
|
|
62
|
+
"unknown-asset": "This project has no file by that name. Reload the page to see its current files.",
|
|
63
|
+
"missing-file": "This file was deleted or moved from the project folder. Use Re-run section on the project page to make it again.",
|
|
64
|
+
"no-images": "This project has no images or thumbnail yet. Wait for the Images step to finish, then try again.",
|
|
65
65
|
};
|
|
66
66
|
return problem(c, { status: 404, title: titleOf(404), detail: details[reason] });
|
|
67
67
|
}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
2
|
+
const dockerHost = { location: z.literal("docker-host"), path: z.string().min(1) };
|
|
3
|
+
// In Docker the host helper may open the folder itself; the host path is sent either way.
|
|
4
|
+
export const folderReplySchema = z.union([
|
|
3
5
|
z.object({ opened: z.literal(true) }).strict(),
|
|
4
|
-
z
|
|
5
|
-
|
|
6
|
-
opened: z.literal(false),
|
|
7
|
-
location: z.literal("docker-host"),
|
|
8
|
-
path: z.string().min(1),
|
|
9
|
-
})
|
|
10
|
-
.strict(),
|
|
6
|
+
z.object({ opened: z.literal(true), ...dockerHost }).strict(),
|
|
7
|
+
z.object({ opened: z.literal(false), ...dockerHost }).strict(),
|
|
11
8
|
]);
|
|
@@ -10,7 +10,7 @@ export async function replyForFolder(c, deps, projectId, file) {
|
|
|
10
10
|
return problem(c, {
|
|
11
11
|
status: 503,
|
|
12
12
|
title: titleOf(503),
|
|
13
|
-
detail: "
|
|
13
|
+
detail: "Slopify cannot show where this file is on your computer because its Docker project folder was not set up. You can still use the download buttons, or run the Slopify Docker launcher again to set up the folder.",
|
|
14
14
|
});
|
|
15
15
|
try {
|
|
16
16
|
const r = relative(deps.paths.projects, file);
|
|
@@ -27,11 +27,16 @@ export async function replyForFolder(c, deps, projectId, file) {
|
|
|
27
27
|
if (s.isSymbolicLink() || (i === parts.length - 1 ? !s.isFile() : !s.isDirectory()))
|
|
28
28
|
throw new Error("Unavailable output");
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
const hostPath = join(host, dirname(r));
|
|
31
|
+
const opened = (await deps.folderLocation
|
|
32
|
+
.openOnHost?.(hostPath, AbortSignal.timeout(10_000))
|
|
33
|
+
.catch(() => false)) === true;
|
|
34
|
+
if (!opened && deps.folderLocation.openOnHost)
|
|
35
|
+
deps.log.write("warn", "project.open-folder", {
|
|
36
|
+
projectId,
|
|
37
|
+
detail: "The host helper did not open the folder (not installed, too old, or it refused), so the host path was shown instead.",
|
|
38
|
+
});
|
|
39
|
+
return c.json(folderReplySchema.parse({ opened, location: "docker-host", path: hostPath }));
|
|
35
40
|
}
|
|
36
41
|
catch {
|
|
37
42
|
deps.log.write("warn", "project.locate-folder", {
|
|
@@ -41,7 +46,7 @@ export async function replyForFolder(c, deps, projectId, file) {
|
|
|
41
46
|
return problem(c, {
|
|
42
47
|
status: 404,
|
|
43
48
|
title: titleOf(404),
|
|
44
|
-
detail: "This
|
|
49
|
+
detail: "This output's folder was deleted or moved. Use Re-run section on the project page to make the file again.",
|
|
45
50
|
});
|
|
46
51
|
}
|
|
47
52
|
}
|
|
@@ -59,7 +64,7 @@ export async function replyForFolder(c, deps, projectId, file) {
|
|
|
59
64
|
return problem(c, {
|
|
60
65
|
status: 503,
|
|
61
66
|
title: titleOf(503),
|
|
62
|
-
detail: "
|
|
67
|
+
detail: "Slopify could not open a file manager window on the computer it runs on. Make sure you are signed in to that computer's desktop, or use the download buttons instead.",
|
|
63
68
|
});
|
|
64
69
|
}
|
|
65
70
|
}
|
package/dist/edge/http/fonts.js
CHANGED
|
@@ -17,14 +17,14 @@ export function fontsRoutes(deps) {
|
|
|
17
17
|
return problem(c, {
|
|
18
18
|
status: 415,
|
|
19
19
|
title: titleOf(415),
|
|
20
|
-
detail: "
|
|
20
|
+
detail: "The font was not sent as a file. Reload the page and choose a .ttf or .otf file again.",
|
|
21
21
|
});
|
|
22
22
|
const body = c.req.raw.body;
|
|
23
23
|
if (body === null)
|
|
24
24
|
return problem(c, {
|
|
25
25
|
status: 400,
|
|
26
26
|
title: titleOf(400),
|
|
27
|
-
detail: "
|
|
27
|
+
detail: "No font file arrived. Choose a .ttf or .otf file and try again.",
|
|
28
28
|
});
|
|
29
29
|
const part = await readUpload(contentType, body);
|
|
30
30
|
if (!part.ok) {
|
|
@@ -33,8 +33,8 @@ export function fontsRoutes(deps) {
|
|
|
33
33
|
status: tooLarge ? 413 : 400,
|
|
34
34
|
title: tooLarge ? "Content Too Large" : titleOf(400),
|
|
35
35
|
detail: tooLarge
|
|
36
|
-
? "
|
|
37
|
-
: "
|
|
36
|
+
? "This font file is larger than 32 MB. Choose a smaller .ttf or .otf file."
|
|
37
|
+
: "The font upload did not arrive complete. Choose one .ttf or .otf file and try again.",
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
const result = await uploadFont(deps.paths, part.upload);
|
|
@@ -44,7 +44,11 @@ export function fontsRoutes(deps) {
|
|
|
44
44
|
})
|
|
45
45
|
.get("/:id/file", zValidator("param", idParam, (result, c) => {
|
|
46
46
|
if (!result.success)
|
|
47
|
-
return problem(c, {
|
|
47
|
+
return problem(c, {
|
|
48
|
+
status: 404,
|
|
49
|
+
title: titleOf(404),
|
|
50
|
+
detail: "This font no longer exists; it may have been deleted. Reload the page to see your current fonts.",
|
|
51
|
+
});
|
|
48
52
|
return undefined;
|
|
49
53
|
}), async (c) => {
|
|
50
54
|
try {
|
|
@@ -58,7 +62,11 @@ export function fontsRoutes(deps) {
|
|
|
58
62
|
catch (error) {
|
|
59
63
|
if (!isMissingFont(error))
|
|
60
64
|
throw error;
|
|
61
|
-
return problem(c, {
|
|
65
|
+
return problem(c, {
|
|
66
|
+
status: 404,
|
|
67
|
+
title: titleOf(404),
|
|
68
|
+
detail: "This font no longer exists; it may have been deleted. Reload the page to see your current fonts.",
|
|
69
|
+
});
|
|
62
70
|
}
|
|
63
71
|
});
|
|
64
72
|
}
|
|
@@ -127,21 +135,25 @@ function failure(reason) {
|
|
|
127
135
|
return {
|
|
128
136
|
status: 413,
|
|
129
137
|
title: "Content Too Large",
|
|
130
|
-
detail: "
|
|
138
|
+
detail: "This font file is larger than 32 MB. Choose a smaller .ttf or .otf file.",
|
|
131
139
|
};
|
|
132
140
|
case "unsupported-format":
|
|
133
|
-
return {
|
|
141
|
+
return {
|
|
142
|
+
status: 415,
|
|
143
|
+
title: titleOf(415),
|
|
144
|
+
detail: "Slopify only accepts .ttf or .otf font files. Choose a file with one of those endings.",
|
|
145
|
+
};
|
|
134
146
|
case "unsafe-filename":
|
|
135
147
|
return {
|
|
136
148
|
status: 400,
|
|
137
149
|
title: titleOf(400),
|
|
138
|
-
detail: "The font
|
|
150
|
+
detail: "The font's file name contains characters Slopify cannot use. Rename the file on your computer, then upload it again.",
|
|
139
151
|
};
|
|
140
152
|
case "invalid-font":
|
|
141
153
|
return {
|
|
142
154
|
status: 400,
|
|
143
155
|
title: titleOf(400),
|
|
144
|
-
detail: "This file is not a
|
|
156
|
+
detail: "This file is not a valid TrueType (.ttf) or OpenType (.otf) font; it may be damaged. Download the font again or choose another.",
|
|
145
157
|
};
|
|
146
158
|
}
|
|
147
159
|
}
|