@jokerized/decksmith 0.5.0 → 0.5.2
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 +7 -4
- package/dist/cli.js +5 -6
- package/dist/index.js +5 -6
- package/dist/mcp.js +1 -2
- package/dist/types/types.d.ts +23 -0
- package/dist/types/verify/budget.d.ts +10 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ storyboard rendered to a 9:16 short or an MP4 without replanning.
|
|
|
6
6
|
|
|
7
7
|
Rendering is bought, not built. A deck is a
|
|
8
8
|
[HyperFrames](https://github.com/heygen-com/hyperframes) composition (Apache-2.0, pinned
|
|
9
|
-
at 0.8.
|
|
9
|
+
at 0.8.43), so the animation runtime, the headless capture and the FFmpeg encode are
|
|
10
10
|
upstream's. What DeckSmith owns is the part nothing else does well: turning a document
|
|
11
11
|
into a *good explanation*, and being able to check that the explanation is true to its
|
|
12
12
|
source.
|
|
@@ -420,9 +420,12 @@ not a polish gap:
|
|
|
420
420
|
|
|
421
421
|
- **No authentication and no TLS.** Anyone who can reach the port can spend your Codex
|
|
422
422
|
quota. This is why the default bind is loopback.
|
|
423
|
-
- **
|
|
424
|
-
|
|
425
|
-
|
|
423
|
+
- **DNS rebinding is refused only on a loopback bind.** A write another site's page makes
|
|
424
|
+
a browser send is refused on any bind: `Sec-Fetch-Site`, or `Origin` where that is
|
|
425
|
+
missing. But a rebinding page is same-origin to itself, and the only thing that gives it
|
|
426
|
+
away is a `Host` naming something other than the server. On `127.0.0.1` that check is
|
|
427
|
+
on. On any other `DECKSMITH_HOST` the server cannot know its own names, so the check is
|
|
428
|
+
off until it is given an allowlist.
|
|
426
429
|
- **Codex spend is unmetered per upload.** The per-IP hourly limit is the only brake, and
|
|
427
430
|
it is per-IP.
|
|
428
431
|
- **Rate limiting is by `socket.remoteAddress` only.** `X-Forwarded-For` is deliberately
|
package/dist/cli.js
CHANGED
|
@@ -1092,8 +1092,7 @@ var DESTINATIONS = {
|
|
|
1092
1092
|
"video-16x9": [],
|
|
1093
1093
|
"short-9x16": [
|
|
1094
1094
|
{ name: "YouTube Shorts", maxSeconds: 180 },
|
|
1095
|
-
{ name: "Instagram Reels", maxSeconds: 180 }
|
|
1096
|
-
{ name: "Facebook Reels", maxSeconds: 90 }
|
|
1095
|
+
{ name: "Instagram Reels", maxSeconds: 180 }
|
|
1097
1096
|
],
|
|
1098
1097
|
"post-1x1": [{ name: "X (standard account)", maxSeconds: 140 }]
|
|
1099
1098
|
};
|
|
@@ -11547,13 +11546,13 @@ function readCanvas(html) {
|
|
|
11547
11546
|
if (width === void 0 || height === void 0 || seconds === void 0) return void 0;
|
|
11548
11547
|
return { width, height, seconds };
|
|
11549
11548
|
}
|
|
11550
|
-
function profilesFor(width, height) {
|
|
11551
|
-
return Object.values(
|
|
11549
|
+
function profilesFor(width, height, formats = FORMATS) {
|
|
11550
|
+
return Object.values(formats).filter((f) => f.width === width && f.height === height);
|
|
11552
11551
|
}
|
|
11553
|
-
function scanBudget(html, storyboard, kept) {
|
|
11552
|
+
function scanBudget(html, storyboard, kept, formats = FORMATS) {
|
|
11554
11553
|
const canvas = readCanvas(html);
|
|
11555
11554
|
if (!canvas) return [];
|
|
11556
|
-
const profiles = profilesFor(canvas.width, canvas.height);
|
|
11555
|
+
const profiles = profilesFor(canvas.width, canvas.height, formats);
|
|
11557
11556
|
if (profiles.length === 0) {
|
|
11558
11557
|
return [
|
|
11559
11558
|
{
|
package/dist/index.js
CHANGED
|
@@ -1087,8 +1087,7 @@ var DESTINATIONS = {
|
|
|
1087
1087
|
"video-16x9": [],
|
|
1088
1088
|
"short-9x16": [
|
|
1089
1089
|
{ name: "YouTube Shorts", maxSeconds: 180 },
|
|
1090
|
-
{ name: "Instagram Reels", maxSeconds: 180 }
|
|
1091
|
-
{ name: "Facebook Reels", maxSeconds: 90 }
|
|
1090
|
+
{ name: "Instagram Reels", maxSeconds: 180 }
|
|
1092
1091
|
],
|
|
1093
1092
|
"post-1x1": [{ name: "X (standard account)", maxSeconds: 140 }]
|
|
1094
1093
|
};
|
|
@@ -10934,13 +10933,13 @@ function readCanvas(html) {
|
|
|
10934
10933
|
if (width === void 0 || height === void 0 || seconds === void 0) return void 0;
|
|
10935
10934
|
return { width, height, seconds };
|
|
10936
10935
|
}
|
|
10937
|
-
function profilesFor(width, height) {
|
|
10938
|
-
return Object.values(
|
|
10936
|
+
function profilesFor(width, height, formats = FORMATS) {
|
|
10937
|
+
return Object.values(formats).filter((f) => f.width === width && f.height === height);
|
|
10939
10938
|
}
|
|
10940
|
-
function scanBudget(html, storyboard, kept) {
|
|
10939
|
+
function scanBudget(html, storyboard, kept, formats = FORMATS) {
|
|
10941
10940
|
const canvas = readCanvas(html);
|
|
10942
10941
|
if (!canvas) return [];
|
|
10943
|
-
const profiles = profilesFor(canvas.width, canvas.height);
|
|
10942
|
+
const profiles = profilesFor(canvas.width, canvas.height, formats);
|
|
10944
10943
|
if (profiles.length === 0) {
|
|
10945
10944
|
return [
|
|
10946
10945
|
{
|
package/dist/mcp.js
CHANGED
|
@@ -1118,8 +1118,7 @@ var DESTINATIONS = {
|
|
|
1118
1118
|
"video-16x9": [],
|
|
1119
1119
|
"short-9x16": [
|
|
1120
1120
|
{ name: "YouTube Shorts", maxSeconds: 180 },
|
|
1121
|
-
{ name: "Instagram Reels", maxSeconds: 180 }
|
|
1122
|
-
{ name: "Facebook Reels", maxSeconds: 90 }
|
|
1121
|
+
{ name: "Instagram Reels", maxSeconds: 180 }
|
|
1123
1122
|
],
|
|
1124
1123
|
"post-1x1": [{ name: "X (standard account)", maxSeconds: 140 }]
|
|
1125
1124
|
};
|
package/dist/types/types.d.ts
CHANGED
|
@@ -2531,6 +2531,29 @@ export interface Destination {
|
|
|
2531
2531
|
* Verified by hand, not by network (nothing here may reach one). These move;
|
|
2532
2532
|
* when one does, the finding it produces names it, so the stale number is
|
|
2533
2533
|
* findable from the message rather than only from this file.
|
|
2534
|
+
*
|
|
2535
|
+
* LAST CHECKED 2026-09-17, against each platform's own pages where they would
|
|
2536
|
+
* load. And it happened again: FACEBOOK REELS IS GONE, because its 90 was stale
|
|
2537
|
+
* the same way Instagram's once was. Meta's newsroom, 2025-06-17: "Reels on
|
|
2538
|
+
* Facebook will also not have any length or format restrictions." By the rule
|
|
2539
|
+
* above a platform that takes anything adds nothing but slack — and the 90 was
|
|
2540
|
+
* not harmless slack, it was the tightest entry, so it made `near_budget` tell
|
|
2541
|
+
* every short between 1m30s and 3m00s that it was "not postable everywhere",
|
|
2542
|
+
* naming a destination that would have taken it. The 90 had been flagged in
|
|
2543
|
+
* EXPERIMENT-010 as "from memory, not the network" for months before anyone
|
|
2544
|
+
* looked.
|
|
2545
|
+
*
|
|
2546
|
+
* Note what each remaining number MEANS, because they are not the same thing:
|
|
2547
|
+
*
|
|
2548
|
+
* - YouTube Shorts, 180 — a CLASSIFICATION limit. A vertical or square upload of
|
|
2549
|
+
* three minutes or less is a Short; longer is long-form, off the Shorts feed.
|
|
2550
|
+
* YouTube Help, "Understand three-minute YouTube Shorts".
|
|
2551
|
+
* - Instagram Reels, 180 — a DISTRIBUTION limit, not an upload cap. Uploads run
|
|
2552
|
+
* longer, but "we recommend videos to unconnected audiences that are 3 minutes
|
|
2553
|
+
* or less" (Instagram for Creators, FAQ). For a short, reaching people who do
|
|
2554
|
+
* not follow you is the point, so this is the limit that constrains it.
|
|
2555
|
+
* - X, standard account, 140 — NOT verified at source: X's help centre refused
|
|
2556
|
+
* the fetch. Every secondary source agrees and it has not moved in years.
|
|
2534
2557
|
*/
|
|
2535
2558
|
export declare const DESTINATIONS: Readonly<Record<PresetId, readonly Destination[]>>;
|
|
2536
2559
|
/** The loosest destination: what the format may produce at all. */
|
|
@@ -26,7 +26,7 @@ export declare function readCanvas(html: string): Canvas | undefined;
|
|
|
26
26
|
* be its own is a gate people learn to ignore. Today the two 16:9 profiles have
|
|
27
27
|
* the same (absent) budget, so the reading is exact as well as safe.
|
|
28
28
|
*/
|
|
29
|
-
export declare function profilesFor(width: number, height: number): Format[];
|
|
29
|
+
export declare function profilesFor(width: number, height: number, formats?: Readonly<Record<string, Format>>): Format[];
|
|
30
30
|
/**
|
|
31
31
|
* The budget finding for one built composition, if there is one.
|
|
32
32
|
*
|
|
@@ -37,5 +37,13 @@ export declare function profilesFor(width: number, height: number): Format[];
|
|
|
37
37
|
* length of the beat at the same index, and getting that pairing wrong would
|
|
38
38
|
* attribute one beat's seconds to another. Absent, it is re-derived with the
|
|
39
39
|
* flat threshold, which is the same list only while the budget cut nothing.
|
|
40
|
+
*
|
|
41
|
+
* `formats` is a seam for the test and nothing else, and it exists because of
|
|
42
|
+
* what the shipped table stopped containing. `near_budget` fires only when a
|
|
43
|
+
* format's destinations DISAGREE, and since Facebook Reels left `DESTINATIONS`
|
|
44
|
+
* on 2026-09-17 none of them do. A branch no shipped format can reach is a gate
|
|
45
|
+
* that cannot fail — the thing this project keeps finding — so the test hands in
|
|
46
|
+
* a table that disagrees, rather than the rule being deleted and silently absent
|
|
47
|
+
* the next time a real destination is tighter than the rest.
|
|
40
48
|
*/
|
|
41
|
-
export declare function scanBudget(html: string, storyboard?: Storyboard, kept?: readonly Beat[]): Finding[];
|
|
49
|
+
export declare function scanBudget(html: string, storyboard?: Storyboard, kept?: readonly Beat[], formats?: Readonly<Record<string, Format>>): Finding[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jokerized/decksmith",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Turn a source document into an animated explanation deck.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"commander": "^14.0.1",
|
|
64
64
|
"fflate": "^0.8.3",
|
|
65
65
|
"gsap": "^3.14.2",
|
|
66
|
-
"hyperframes": "0.8.
|
|
66
|
+
"hyperframes": "0.8.43",
|
|
67
67
|
"katex": "^0.16.11",
|
|
68
68
|
"puppeteer-core": "^25.3.0",
|
|
69
69
|
"remark-gfm": "^4.0.1",
|