@gentbajko/slopify 1.1.1 → 1.2.1

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.
@@ -6,7 +6,7 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
7
  <meta name="color-scheme" content="dark light" />
8
8
  <title>Slopify</title>
9
- <script type="module" crossorigin src="/assets/index-DwM-Y6nw.js"></script>
9
+ <script type="module" crossorigin src="/assets/index-Cq2O1JRf.js"></script>
10
10
  <link rel="stylesheet" crossorigin href="/assets/index-DX1_chKs.css">
11
11
  </head>
12
12
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gentbajko/slopify",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "description": "Turn a prompt into a finished video, locally, with your own provider keys",
5
5
  "license": "MIT",
6
6
  "author": "Gent Bajko",
@@ -19,6 +19,7 @@
19
19
  "files": [
20
20
  "dist",
21
21
  "SUBTITLES.md",
22
+ "scripts/docker-run.sh",
22
23
  "!dist/**/*.d.ts"
23
24
  ],
24
25
  "scripts": {
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ if [[ "$(uname -s)" != Linux ]]; then
5
+ echo "Host CLI bridging requires Linux executables. Use the API providers on this host." >&2
6
+ exit 1
7
+ fi
8
+
9
+ image=${SLOPIFY_DOCKER_IMAGE:-ghcr.io/gentbajko/slopify:latest}
10
+ container=${SLOPIFY_DOCKER_NAME:-slopify}
11
+ volume=${SLOPIFY_DOCKER_VOLUME:-slopify-data}
12
+ host_port=${SLOPIFY_DOCKER_HOST_PORT:-6969}
13
+ if [[ ! "$host_port" =~ ^[0-9]{1,5}$ ]] || (( host_port > 65535 )); then
14
+ echo "SLOPIFY_DOCKER_HOST_PORT must be a port from 0 to 65535." >&2
15
+ exit 1
16
+ fi
17
+ published_port=$host_port
18
+ if [[ "$host_port" == 0 ]]; then published_port=""; fi
19
+
20
+ mounts=()
21
+ environment=()
22
+ installations=()
23
+ if [[ -n ${GEMINI_API_KEY:-} ]]; then environment+=(--env GEMINI_API_KEY); fi
24
+
25
+ bridge_node_package() {
26
+ local command_name=$1 expected_package=$2 target=$3
27
+ local launcher package_dir actual_package
28
+ launcher=$(command -v "$command_name") || return 0
29
+ launcher=$(readlink -f "$launcher")
30
+ package_dir=$(dirname "$(dirname "$launcher")")
31
+ if [[ ! -f "$package_dir/package.json" ]]; then
32
+ echo "Cannot bridge $command_name: expected an npm package around $launcher." >&2
33
+ exit 1
34
+ fi
35
+ actual_package=$(node -p 'require(process.argv[1]).name' "$package_dir/package.json")
36
+ if [[ "$actual_package" != "$expected_package" ]]; then
37
+ echo "Cannot bridge $command_name: $launcher is not from $expected_package." >&2
38
+ exit 1
39
+ fi
40
+ mounts+=(--mount "type=bind,source=$package_dir,target=$target,readonly")
41
+ installations+=("$(stat -Lc '%d:%i' "$package_dir")")
42
+ echo "Detected $command_name: $launcher" >&2
43
+ }
44
+
45
+ bridge_node_package codex @openai/codex /opt/host-clis/codex
46
+ bridge_node_package gemini @google/gemini-cli /opt/host-clis/gemini
47
+
48
+ # Model metadata is separate from login state. Mount only this file, never the
49
+ # user's Codex home, which also contains credentials and conversation history.
50
+ codex_models=${CODEX_HOME:-$HOME/.codex}/models_cache.json
51
+ if command -v codex >/dev/null 2>&1 && [[ -f "$codex_models" ]]; then
52
+ codex_models=$(readlink -f "$codex_models")
53
+ mounts+=(--mount "type=bind,source=$codex_models,target=/opt/host-cli-data/codex-models.json,readonly")
54
+ environment+=(--env SLOPIFY_CODEX_MODELS_FILE=/opt/host-cli-data/codex-models.json)
55
+ installations+=("$(stat -Lc '%d:%i' "$codex_models")")
56
+ fi
57
+
58
+ if command -v claude >/dev/null 2>&1; then
59
+ claude_binary=$(readlink -f "$(command -v claude)")
60
+ if [[ "$(head -c 4 "$claude_binary")" != $'\177ELF' ]]; then
61
+ echo "Cannot bridge claude: this launcher is not a native Linux executable." >&2
62
+ exit 1
63
+ fi
64
+ mounts+=(--mount "type=bind,source=$claude_binary,target=/opt/host-clis/claude,readonly")
65
+ installations+=("$(stat -Lc '%d:%i' "$claude_binary")")
66
+ echo "Detected claude: $claude_binary" >&2
67
+ fi
68
+
69
+ if ! docker image inspect "$image" >/dev/null 2>&1; then docker pull "$image"; fi
70
+ image_id=$(docker image inspect --format '{{.Id}}' "$image")
71
+ # Changing an installation path or image requires new bind mounts. Re-running
72
+ # the launcher reconciles those automatically while keeping the named data volume.
73
+ signature=$(printf '%s\0' "$image_id" "$volume" "$host_port" "${mounts[@]}" "${installations[@]}" "${environment[@]}" "${GEMINI_API_KEY:-}" | sha256sum | cut -d ' ' -f 1)
74
+ previous=""
75
+ if docker container inspect "$container" >/dev/null 2>&1; then
76
+ existing_signature=$(docker inspect --format '{{index .Config.Labels "io.slopify.launcher"}}' "$container")
77
+ if [[ "$existing_signature" == "$signature" ]]; then
78
+ docker start "$container" >/dev/null
79
+ echo "Slopify is running at http://$(docker port "$container" 6969/tcp)"
80
+ exit 0
81
+ fi
82
+ existing_volume=$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/data"}}{{.Name}}{{end}}{{end}}' "$container")
83
+ if [[ "$existing_volume" != "$volume" ]]; then
84
+ echo "Container $container uses a different data mount. Set SLOPIFY_DOCKER_NAME to a new name or select its existing SLOPIFY_DOCKER_VOLUME." >&2
85
+ exit 1
86
+ fi
87
+ previous="$container-previous-$(date +%Y%m%d%H%M%S)"
88
+ previous_restart=$(docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' "$container")
89
+ docker update --restart=no "$container" >/dev/null
90
+ docker stop "$container" >/dev/null
91
+ docker rename "$container" "$previous"
92
+ fi
93
+
94
+ if ! docker run -d \
95
+ --name "$container" \
96
+ --label "io.slopify.launcher=$signature" \
97
+ --restart always \
98
+ -p "127.0.0.1:$published_port:6969" \
99
+ --mount "type=volume,source=$volume,target=/data" \
100
+ "${mounts[@]}" \
101
+ "${environment[@]}" \
102
+ "$image"; then
103
+ if [[ -n "$previous" ]]; then
104
+ failed_signature=$(docker inspect --format '{{index .Config.Labels "io.slopify.launcher"}}' "$container" 2>/dev/null || true)
105
+ if [[ "$failed_signature" == "$signature" ]]; then docker rm -f "$container" >/dev/null; fi
106
+ docker rename "$previous" "$container"
107
+ docker update --restart="$previous_restart" "$container" >/dev/null
108
+ docker start "$container" >/dev/null
109
+ fi
110
+ exit 1
111
+ fi
112
+ echo "Slopify is starting at http://$(docker port "$container" 6969/tcp)"
113
+ if [[ -n "$previous" ]]; then echo "Previous container kept stopped as $previous."; fi