@impractical-ai/motion 0.1.10 → 0.1.12
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/README.md +64 -0
- package/assets/engine.d.ts +1015 -682
- package/assets/impractical/SKILL.md +12 -0
- package/dist/{api-4WE4LYPB.js → api-3IX5MBOY.js} +2 -2
- package/dist/{chunk-WB7FRXAG.js → chunk-4JSZNV7I.js} +2 -2
- package/dist/{chunk-CZANULCU.js → chunk-6GR7BQDV.js} +4 -1
- package/dist/{chunk-6FVZ6IWR.js → chunk-ACBYTWXK.js} +6 -4
- package/dist/{commands-YJFMKK2K.js → commands-K6AOA7CK.js} +139 -3
- package/dist/index.js +25 -5
- package/dist/{main-BEONOBG5.js → main-72BNF5J2.js} +2 -2
- package/dist/stdio-HFGQR34V.js +72653 -0
- package/package.json +5 -3
- package/dist/stdio-S7VGBKNS.js +0 -36204
|
@@ -5,6 +5,18 @@ description: Create and refine studio-quality motion-graphics launch videos with
|
|
|
5
5
|
|
|
6
6
|
# Impractical Motion
|
|
7
7
|
|
|
8
|
+
<!-- ARRIVAL-DRIFT-STANDARD START -->
|
|
9
|
+
## Default motion: arrival and residual drift
|
|
10
|
+
|
|
11
|
+
Foreground motion defaults to an energetic arrival, strong deceleration, and small continuing travel through the reading hold. Compose a deterministic residual trajectory with the native entrance; do not stop and restart with a disconnected tween. “Settled” and “hold” mean readable and visually stable, with subtle nonzero travel unless an explicit freeze, exact alignment or reduced-motion mode requires stillness.
|
|
12
|
+
|
|
13
|
+
Use the Rox `ambientOffset(seconds, amount, phase)` pattern: native 960×540 product groups start around amount 3.2–4, text around 0.8–1. Keep a signed velocity floor with gentle curvature, not a pure sine bob. Move attached labels, controls, connectors and shadows together, avoid double drift, preserve 3D hierarchy, and verify reverse/retimed seeks and late-hold displacement.
|
|
14
|
+
|
|
15
|
+
The host owns the background environment. Animate foreground objects only; never move or retime the background to simulate object motion. Reusable foregrounds should be transparent. Keep one primary focus and room around it; purposeful object camera moves remain welcome, and a generic card is not the default visual container.
|
|
16
|
+
|
|
17
|
+
For the complete trajectory and review checks, read `motion_context` → `guidance.director` before authoring.
|
|
18
|
+
<!-- ARRIVAL-DRIFT-STANDARD END -->
|
|
19
|
+
|
|
8
20
|
You direct the video yourself. Impractical provides the engine, the preview
|
|
9
21
|
build, the render, and the studio the user tweaks in — you provide the
|
|
10
22
|
direction. Everything runs through the **Impractical MCP server**; the video's
|
|
@@ -13,8 +13,8 @@ import {
|
|
|
13
13
|
waitForJobs,
|
|
14
14
|
withAdmissionReceipt,
|
|
15
15
|
withMeteredCall
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
} from "./chunk-6GR7BQDV.js";
|
|
17
|
+
import "./chunk-ACBYTWXK.js";
|
|
18
18
|
import "./chunk-77HVPD4G.js";
|
|
19
19
|
export {
|
|
20
20
|
ApiContractError,
|
|
@@ -6,14 +6,14 @@ import {
|
|
|
6
6
|
loadConfig,
|
|
7
7
|
recoverCorruptConfig,
|
|
8
8
|
saveConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-6GR7BQDV.js";
|
|
10
10
|
import {
|
|
11
11
|
PACKAGE_COMMAND,
|
|
12
12
|
PACKAGE_NAME,
|
|
13
13
|
PACKAGE_VERSION,
|
|
14
14
|
PRODUCTION_APP_URL,
|
|
15
15
|
PRODUCTION_SUPABASE_URL
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-ACBYTWXK.js";
|
|
17
17
|
|
|
18
18
|
// src/onboarding.ts
|
|
19
19
|
import {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
PRODUCTION_APP_URL,
|
|
4
4
|
PRODUCTION_SUPABASE_URL
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ACBYTWXK.js";
|
|
6
6
|
|
|
7
7
|
// src/config.ts
|
|
8
8
|
import {
|
|
@@ -141,6 +141,9 @@ function bodyRecord(body) {
|
|
|
141
141
|
function validateApiResponse(name, body, data) {
|
|
142
142
|
if (!isRecord(data)) throw new ApiContractError(name, "a JSON object");
|
|
143
143
|
const input = bodyRecord(body);
|
|
144
|
+
if (name === "video-shares" && input.action === "clone" && (typeof data.projectId !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(data.projectId) || typeof data.alreadyForked !== "boolean")) {
|
|
145
|
+
throw new ApiContractError(name, "a projectId and alreadyForked flag");
|
|
146
|
+
}
|
|
144
147
|
if (name === "workspace-bootstrap") {
|
|
145
148
|
const billing = data.billing;
|
|
146
149
|
if (typeof data.orgId !== "string" || typeof data.plan !== "string" || typeof data.hasAccess !== "boolean" || !isRecord(billing) || typeof billing.status !== "string") {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@impractical-ai/motion",
|
|
6
|
-
version: "0.1.
|
|
6
|
+
version: "0.1.12",
|
|
7
7
|
private: false,
|
|
8
8
|
description: "Create and refine Impractical Motion videos from coding agents and the terminal.",
|
|
9
9
|
homepage: "https://github.com/Openpod/impractical-motion#readme",
|
|
@@ -18,7 +18,8 @@ var package_default = {
|
|
|
18
18
|
type: "module",
|
|
19
19
|
files: [
|
|
20
20
|
"dist",
|
|
21
|
-
"assets",
|
|
21
|
+
"assets/impractical",
|
|
22
|
+
"assets/engine.d.ts",
|
|
22
23
|
"README.md"
|
|
23
24
|
],
|
|
24
25
|
bin: {
|
|
@@ -31,7 +32,8 @@ var package_default = {
|
|
|
31
32
|
build: 'node ../scripts/verify-locked-cli-install.mjs && node ../scripts/build-engine-dts.mjs --cli-only && rm -rf dist && ./node_modules/esbuild/bin/esbuild src/index.ts --define:__BUILD_COMMIT__=\\"$(git rev-parse --short HEAD 2>/dev/null || echo dev)\\" --bundle --platform=node --format=esm --target=node22 --splitting --outdir=dist --external:playwright-core --banner:js="#!/usr/bin/env node" && chmod +x dist/index.js',
|
|
32
33
|
typecheck: "tsc --noEmit",
|
|
33
34
|
test: "npm run typecheck && npm run build && esbuild tests/onboarding.test.ts tests/mcp-tools.test.ts tests/mcp-frames.test.ts tests/mcp-browser-pool.test.ts tests/mcp-motion.test.ts tests/mcp-craft.test.ts tests/mcp-depthkit.test.ts tests/mcp-motion-score.test.ts tests/mcp-install-font.test.ts tests/mcp-metric-catalog.test.ts tests/mcp-text-census.test.ts tests/mcp-phased-flow.test.ts tests/mcp-preflight.test.ts tests/engine-dts.test.ts tests/mcp-connect.test.ts tests/mcp-longpoll.test.ts tests/mcp-agent-timeout.test.ts tests/api-hardening.test.ts --bundle --platform=node --format=esm --packages=external --outdir=dist --out-extension:.js=.mjs && node --test dist/onboarding.test.mjs dist/mcp-tools.test.mjs dist/mcp-frames.test.mjs dist/mcp-browser-pool.test.mjs dist/mcp-motion.test.mjs dist/mcp-craft.test.mjs dist/mcp-depthkit.test.mjs dist/mcp-motion-score.test.mjs dist/mcp-install-font.test.mjs dist/mcp-metric-catalog.test.mjs dist/mcp-text-census.test.mjs dist/mcp-phased-flow.test.mjs dist/mcp-preflight.test.mjs dist/engine-dts.test.mjs dist/mcp-connect.test.mjs dist/mcp-longpoll.test.mjs dist/mcp-agent-timeout.test.mjs dist/api-hardening.test.mjs",
|
|
34
|
-
prepack: "npm run build"
|
|
35
|
+
prepack: "npm run build",
|
|
36
|
+
"test:rig": "npm run typecheck && esbuild tests/engine-dts.test.ts tests/mcp-agent-timeout.test.ts tests/mcp-browser-pool.test.ts tests/mcp-component-assertions.test.ts tests/mcp-components.test.ts tests/mcp-connect.test.ts tests/mcp-craft.test.ts tests/mcp-depthkit.test.ts tests/mcp-exposed-ground.test.ts tests/mcp-frames.test.ts tests/mcp-install-font.test.ts tests/mcp-legibility.test.ts tests/mcp-longpoll.test.ts tests/mcp-metric-catalog.test.ts tests/mcp-motion-score.test.ts tests/mcp-motion-slop.test.ts tests/mcp-motion.test.ts tests/mcp-phased-flow.test.ts tests/mcp-preflight.test.ts tests/mcp-ref-inject.test.ts tests/mcp-shot-list.test.ts tests/mcp-text-census.test.ts tests/mcp-tools.test.ts tests/review-modules.test.ts tests/rig-transplant.test.ts --bundle --platform=node --format=esm --packages=external --outdir=.rig-tests --out-extension:.js=.mjs && node --test .rig-tests/engine-dts.test.mjs .rig-tests/mcp-agent-timeout.test.mjs .rig-tests/mcp-browser-pool.test.mjs .rig-tests/mcp-component-assertions.test.mjs .rig-tests/mcp-components.test.mjs .rig-tests/mcp-connect.test.mjs .rig-tests/mcp-craft.test.mjs .rig-tests/mcp-depthkit.test.mjs .rig-tests/mcp-exposed-ground.test.mjs .rig-tests/mcp-frames.test.mjs .rig-tests/mcp-install-font.test.mjs .rig-tests/mcp-legibility.test.mjs .rig-tests/mcp-longpoll.test.mjs .rig-tests/mcp-metric-catalog.test.mjs .rig-tests/mcp-motion-score.test.mjs .rig-tests/mcp-motion-slop.test.mjs .rig-tests/mcp-motion.test.mjs .rig-tests/mcp-phased-flow.test.mjs .rig-tests/mcp-preflight.test.mjs .rig-tests/mcp-ref-inject.test.mjs .rig-tests/mcp-shot-list.test.mjs .rig-tests/mcp-text-census.test.mjs .rig-tests/mcp-tools.test.mjs .rig-tests/review-modules.test.mjs .rig-tests/rig-transplant.test.mjs"
|
|
35
37
|
},
|
|
36
38
|
publishConfig: {
|
|
37
39
|
access: "public"
|
|
@@ -56,7 +58,7 @@ var PRODUCTION_APP_URL = "https://motion.impractical.ai";
|
|
|
56
58
|
var PRODUCTION_SUPABASE_URL = "https://uaxjweednprtbhbceify.supabase.co";
|
|
57
59
|
var PACKAGE_NAME = "@impractical-ai/motion";
|
|
58
60
|
var PACKAGE_VERSION = package_default.version;
|
|
59
|
-
var BUILD_COMMIT = "
|
|
61
|
+
var BUILD_COMMIT = "3fd1ba6" ? "3fd1ba6" : "dev";
|
|
60
62
|
var BUILD_ID = `${PACKAGE_VERSION}+${BUILD_COMMIT}`;
|
|
61
63
|
var PACKAGE_COMMAND = `npx --yes ${PACKAGE_NAME}`;
|
|
62
64
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
setup
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4JSZNV7I.js";
|
|
5
5
|
import {
|
|
6
6
|
invoke,
|
|
7
7
|
invokeAt,
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
saveConfig,
|
|
12
12
|
studioLink,
|
|
13
13
|
waitForJobs
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-6GR7BQDV.js";
|
|
15
|
+
import "./chunk-ACBYTWXK.js";
|
|
16
16
|
import "./chunk-77HVPD4G.js";
|
|
17
17
|
|
|
18
18
|
// src/commands.ts
|
|
@@ -1204,6 +1204,133 @@ function buildInitialFiles(input) {
|
|
|
1204
1204
|
// ../src/shared/video-models.ts
|
|
1205
1205
|
var DEFAULT_OPENROUTER_VIDEO_MODEL = "anthropic/claude-opus-5";
|
|
1206
1206
|
|
|
1207
|
+
// ../src/shared/video-clone-command.ts
|
|
1208
|
+
var TOKEN = /^[A-Za-z0-9_-]{43}$/;
|
|
1209
|
+
var SHARE_HOSTS = /* @__PURE__ */ new Set(["impractical.ai", "www.impractical.ai", "impractical-video-shares.vercel.app"]);
|
|
1210
|
+
function videoShareToken(source) {
|
|
1211
|
+
if (TOKEN.test(source)) return source;
|
|
1212
|
+
try {
|
|
1213
|
+
const url = new URL(source);
|
|
1214
|
+
const token = url.pathname.match(/^\/v\/([A-Za-z0-9_-]{43})\/?$/)?.[1];
|
|
1215
|
+
if (url.protocol === "https:" && SHARE_HOSTS.has(url.host) && !url.username && !url.password && !url.search && !url.hash && token) return token;
|
|
1216
|
+
} catch {
|
|
1217
|
+
}
|
|
1218
|
+
throw new Error("Use an Impractical video share URL: https://impractical.ai/v/<token>");
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
// src/clone-video-project.ts
|
|
1222
|
+
async function cloneVideoProject(source, json = false) {
|
|
1223
|
+
const token = videoShareToken(source);
|
|
1224
|
+
const result = await invoke("video-shares", { action: "clone", token });
|
|
1225
|
+
const url = studioLink(requireConfig().appUrl, result.projectId);
|
|
1226
|
+
if (json) {
|
|
1227
|
+
console.log(JSON.stringify({ ...result, url }, null, 2));
|
|
1228
|
+
return;
|
|
1229
|
+
}
|
|
1230
|
+
console.log(result.alreadyForked ? "Your editable copy is ready." : "Copied the project into your workspace.");
|
|
1231
|
+
console.log(`Open: ${url}`);
|
|
1232
|
+
console.log(`Project: ${result.projectId}`);
|
|
1233
|
+
console.log("After restarting your agent, paste:");
|
|
1234
|
+
console.log(`Use Impractical to open project ${result.projectId} and help me iterate on this video.`);
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
// src/video-sharing.ts
|
|
1238
|
+
import { openAsBlob } from "node:fs";
|
|
1239
|
+
import { readFile, stat } from "node:fs/promises";
|
|
1240
|
+
import { basename as basename2, extname as extname2 } from "node:path";
|
|
1241
|
+
async function shareVideo(rest, flags) {
|
|
1242
|
+
const config = requireConfig();
|
|
1243
|
+
const request = async (body) => {
|
|
1244
|
+
const response = await fetch(
|
|
1245
|
+
`${config.supabaseUrl.replace(/\/$/, "")}/functions/v1/video-shares`,
|
|
1246
|
+
{
|
|
1247
|
+
method: body ? "POST" : "GET",
|
|
1248
|
+
redirect: "error",
|
|
1249
|
+
signal: AbortSignal.timeout(45e3),
|
|
1250
|
+
headers: { authorization: `Bearer ${config.apiKey}`, "content-type": "application/json" },
|
|
1251
|
+
body: body ? JSON.stringify(body) : void 0
|
|
1252
|
+
}
|
|
1253
|
+
);
|
|
1254
|
+
const data = await response.json().catch(() => ({}));
|
|
1255
|
+
if (!response.ok) throw new Error(data.error || `Video sharing failed (${response.status})`);
|
|
1256
|
+
return data;
|
|
1257
|
+
};
|
|
1258
|
+
if (rest[0] === "list") {
|
|
1259
|
+
console.log(JSON.stringify(await request(), null, 2));
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
if (rest[0] === "revoke") {
|
|
1263
|
+
if (!rest[1]) throw new Error("Usage: impractical share revoke <share-id>");
|
|
1264
|
+
await request({ action: "revoke", id: rest[1] });
|
|
1265
|
+
console.log("Share link revoked. Already-open videos may remain playable for up to 5 minutes.");
|
|
1266
|
+
return;
|
|
1267
|
+
}
|
|
1268
|
+
const allowEditing = rest[0] === "allow-editing" || rest[0] === "attach";
|
|
1269
|
+
const viewOnly = rest[0] === "view-only" || rest[0] === "detach";
|
|
1270
|
+
if (allowEditing || viewOnly) {
|
|
1271
|
+
if (!rest[1] || allowEditing && typeof flags.project !== "string") {
|
|
1272
|
+
throw new Error("Usage: impractical share allow-editing <share-id> --project <id> | share view-only <share-id>");
|
|
1273
|
+
}
|
|
1274
|
+
await request({ action: "attach-project", id: rest[1], projectId: viewOnly ? null : flags.project });
|
|
1275
|
+
console.log(allowEditing ? "Editing allowed for this link. Recipients can make their own editable copy." : "This link is now view only. Future project copies are disabled; existing recipient copies remain theirs.");
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1278
|
+
const filePath = rest[0];
|
|
1279
|
+
if (!filePath || extname2(filePath).toLowerCase() !== ".mp4") {
|
|
1280
|
+
throw new Error(
|
|
1281
|
+
'Usage: impractical share ./video.mp4 [--title "A video for Acme"] [--message "..."] [--references ./public-brand.json] [--project <id>] [--expires-in 7] [--json]'
|
|
1282
|
+
);
|
|
1283
|
+
}
|
|
1284
|
+
const info = await stat(filePath);
|
|
1285
|
+
if (!info.isFile() || info.size < 16 || info.size > 3e8) {
|
|
1286
|
+
throw new Error("Choose an MP4 up to 300 MB");
|
|
1287
|
+
}
|
|
1288
|
+
const days = flags["expires-in"] === void 0 ? null : Number(flags["expires-in"]);
|
|
1289
|
+
if (days !== null && (!Number.isFinite(days) || days <= 0 || days > 3650)) {
|
|
1290
|
+
throw new Error("--expires-in must be a number of days between 0 and 3650");
|
|
1291
|
+
}
|
|
1292
|
+
const file = await openAsBlob(filePath, { type: "video/mp4" });
|
|
1293
|
+
const header = new Uint8Array(await file.slice(0, 16).arrayBuffer());
|
|
1294
|
+
if (String.fromCharCode(...header.slice(4, 8)) !== "ftyp") {
|
|
1295
|
+
throw new Error("This file does not have an MP4 header");
|
|
1296
|
+
}
|
|
1297
|
+
let references;
|
|
1298
|
+
if (typeof flags.references === "string") {
|
|
1299
|
+
const metadataFile = await stat(flags.references);
|
|
1300
|
+
if (!metadataFile.isFile() || metadataFile.size > 4e6) throw new Error("Public references must be a JSON file up to 4 MB");
|
|
1301
|
+
references = JSON.parse(await readFile(flags.references, "utf8"));
|
|
1302
|
+
}
|
|
1303
|
+
const prepared = await request({
|
|
1304
|
+
action: "prepare",
|
|
1305
|
+
bytes: info.size,
|
|
1306
|
+
title: typeof flags.title === "string" ? flags.title : basename2(filePath, extname2(filePath)).slice(0, 160),
|
|
1307
|
+
message: typeof flags.message === "string" ? flags.message : "",
|
|
1308
|
+
expiresAt: days === null ? null : new Date(Date.now() + days * 864e5).toISOString(),
|
|
1309
|
+
...references === void 0 ? {} : { references },
|
|
1310
|
+
...typeof flags.project === "string" ? { projectId: flags.project } : {}
|
|
1311
|
+
});
|
|
1312
|
+
try {
|
|
1313
|
+
const form = new FormData();
|
|
1314
|
+
form.append("cacheControl", "0");
|
|
1315
|
+
form.append("", file, basename2(filePath));
|
|
1316
|
+
const response = await fetch(prepared.upload.signedUrl, {
|
|
1317
|
+
method: "PUT",
|
|
1318
|
+
body: form,
|
|
1319
|
+
headers: { "x-upsert": "false" },
|
|
1320
|
+
redirect: "error",
|
|
1321
|
+
signal: AbortSignal.timeout(15 * 6e4)
|
|
1322
|
+
});
|
|
1323
|
+
await response.body?.cancel();
|
|
1324
|
+
if (!response.ok) throw new Error(`MP4 upload failed (${response.status}). Please try again`);
|
|
1325
|
+
const share = await request({ action: "complete", id: prepared.id });
|
|
1326
|
+
console.log(flags.json ? JSON.stringify(share, null, 2) : share.url);
|
|
1327
|
+
} catch (error) {
|
|
1328
|
+
await request({ action: "revoke", id: prepared.id }).catch(() => {
|
|
1329
|
+
});
|
|
1330
|
+
throw error;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1207
1334
|
// src/commands.ts
|
|
1208
1335
|
var flagString = (flags, name) => {
|
|
1209
1336
|
const value = flags[name];
|
|
@@ -1218,6 +1345,8 @@ var flagList = (flags, name) => {
|
|
|
1218
1345
|
var flagBool = (flags, name) => flags[name] === true;
|
|
1219
1346
|
var out = (line) => console.log(line);
|
|
1220
1347
|
async function setup2(flags) {
|
|
1348
|
+
const source = flagString(flags, "from");
|
|
1349
|
+
if (source !== void 0) videoShareToken(source);
|
|
1221
1350
|
const claude = flagBool(flags, "claude");
|
|
1222
1351
|
const agent = flagBool(flags, "agent");
|
|
1223
1352
|
await setup({
|
|
@@ -1227,6 +1356,11 @@ async function setup2(flags) {
|
|
|
1227
1356
|
openBrowser: !flagBool(flags, "no-open"),
|
|
1228
1357
|
log: out
|
|
1229
1358
|
});
|
|
1359
|
+
if (source !== void 0) await cloneVideoProject(source);
|
|
1360
|
+
}
|
|
1361
|
+
async function clone(positional, flags) {
|
|
1362
|
+
if (positional.length !== 1) throw new Error("Usage: impractical clone <video-share-url> [--json]");
|
|
1363
|
+
await cloneVideoProject(positional[0], flagBool(flags, "json"));
|
|
1230
1364
|
}
|
|
1231
1365
|
async function login(flags) {
|
|
1232
1366
|
const patch = {};
|
|
@@ -1522,12 +1656,14 @@ function validateMeteredCommand(command, positional, flags) {
|
|
|
1522
1656
|
}
|
|
1523
1657
|
export {
|
|
1524
1658
|
brand,
|
|
1659
|
+
clone,
|
|
1525
1660
|
exportDraft,
|
|
1526
1661
|
generate,
|
|
1527
1662
|
keys,
|
|
1528
1663
|
link,
|
|
1529
1664
|
login,
|
|
1530
1665
|
setup2 as setup,
|
|
1666
|
+
shareVideo,
|
|
1531
1667
|
status,
|
|
1532
1668
|
upload,
|
|
1533
1669
|
validateMeteredCommand,
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
PACKAGE_VERSION
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ACBYTWXK.js";
|
|
5
5
|
import "./chunk-77HVPD4G.js";
|
|
6
6
|
|
|
7
7
|
// src/cli-args.ts
|
|
@@ -17,6 +17,7 @@ var CLI_OPTIONS = {
|
|
|
17
17
|
brand: { type: "string" },
|
|
18
18
|
asset: { type: "string", multiple: true },
|
|
19
19
|
project: { type: "string" },
|
|
20
|
+
from: { type: "string" },
|
|
20
21
|
feedback: { type: "string" },
|
|
21
22
|
model: { type: "string" },
|
|
22
23
|
slug: { type: "string" },
|
|
@@ -26,6 +27,11 @@ var CLI_OPTIONS = {
|
|
|
26
27
|
out: { type: "string" },
|
|
27
28
|
draft: { type: "string" },
|
|
28
29
|
id: { type: "string" },
|
|
30
|
+
title: { type: "string" },
|
|
31
|
+
message: { type: "string" },
|
|
32
|
+
references: { type: "string" },
|
|
33
|
+
"expires-in": { type: "string" },
|
|
34
|
+
json: { type: "boolean" },
|
|
29
35
|
wait: { type: "boolean" },
|
|
30
36
|
agent: { type: "boolean" },
|
|
31
37
|
claude: { type: "boolean" },
|
|
@@ -48,6 +54,7 @@ var HELP = `impractical \u2014 Impractical Motion from your terminal (and your c
|
|
|
48
54
|
Setup
|
|
49
55
|
setup --claude Sign in and install the Claude plugin + MCP
|
|
50
56
|
setup --agent Sign in and install MCP for detected coding agents
|
|
57
|
+
--from <video-share-url> Also copy the shared project into your workspace
|
|
51
58
|
login --key imk_... Manual credential override for development
|
|
52
59
|
whoami Show org and plan status
|
|
53
60
|
keys [list|revoke <id>] List or revoke agent API keys
|
|
@@ -66,6 +73,15 @@ Edit drafts
|
|
|
66
73
|
Editing happens through the MCP server (see "Agents" above) \u2014 draft source
|
|
67
74
|
lives in the cloud, so there is no working copy to pull or push.
|
|
68
75
|
link <projectId> [slug] Print the studio tweak-UI URL
|
|
76
|
+
clone <video-share-url> Add an editable copy to your connected workspace
|
|
77
|
+
|
|
78
|
+
Share videos
|
|
79
|
+
share <file.mp4> [--title "..."] [--message "..."] [--expires-in 7] [--json]
|
|
80
|
+
[--references brand.json] [--project <id>]
|
|
81
|
+
Omit --project for a view-only link (the default)
|
|
82
|
+
share allow-editing <share-id> --project <id> Let recipients copy and edit
|
|
83
|
+
share view-only <share-id> Hide editing and block future project copies
|
|
84
|
+
share list | share revoke <share-id>
|
|
69
85
|
|
|
70
86
|
Assets & brands
|
|
71
87
|
upload <file> --project <id> --draft <id>
|
|
@@ -97,6 +113,10 @@ async function runCli(args, deps) {
|
|
|
97
113
|
switch (command) {
|
|
98
114
|
case "setup":
|
|
99
115
|
return commands.setup(flags);
|
|
116
|
+
case "clone":
|
|
117
|
+
return commands.clone(rest, flags);
|
|
118
|
+
case "share":
|
|
119
|
+
return commands.shareVideo(rest, flags);
|
|
100
120
|
case "motion":
|
|
101
121
|
if (rest[0] === "wizard") return commands.setup(flags);
|
|
102
122
|
break;
|
|
@@ -140,11 +160,11 @@ async function runCli(args, deps) {
|
|
|
140
160
|
// src/index.ts
|
|
141
161
|
runCli(process.argv.slice(2), {
|
|
142
162
|
writeLine: (line) => console.log(line),
|
|
143
|
-
loadCommands: () => import("./commands-
|
|
144
|
-
loadApi: () => import("./api-
|
|
145
|
-
loadMcp: () => import("./stdio-
|
|
163
|
+
loadCommands: () => import("./commands-K6AOA7CK.js"),
|
|
164
|
+
loadApi: () => import("./api-3IX5MBOY.js"),
|
|
165
|
+
loadMcp: () => import("./stdio-HFGQR34V.js")
|
|
146
166
|
}).catch(async (error) => {
|
|
147
|
-
const { ApiError } = await import("./api-
|
|
167
|
+
const { ApiError } = await import("./api-3IX5MBOY.js");
|
|
148
168
|
if (error instanceof ApiError) {
|
|
149
169
|
console.error(`Error (${error.status} from ${error.fn}): ${error.message}`);
|
|
150
170
|
if (error.status === 429) console.error("Weekly MCP allowance reached. Upgrade or wait for Monday UTC.");
|
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
__require
|
|
5
5
|
} from "./chunk-77HVPD4G.js";
|
|
6
6
|
|
|
7
|
-
// node_modules/esbuild/lib/main.js
|
|
7
|
+
// ../../../../Desktop/impractical-motion/impractical-motion/cli/node_modules/esbuild/lib/main.js
|
|
8
8
|
var require_main = __commonJS({
|
|
9
|
-
"node_modules/esbuild/lib/main.js"(exports, module) {
|
|
9
|
+
"../../../../Desktop/impractical-motion/impractical-motion/cli/node_modules/esbuild/lib/main.js"(exports, module) {
|
|
10
10
|
var __defProp = Object.defineProperty;
|
|
11
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|