@energy8platform/golem 0.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.
Files changed (62) hide show
  1. package/README.md +376 -0
  2. package/bin/golem.js +2 -0
  3. package/dist/editor.css +701 -0
  4. package/dist/editor.js +59202 -0
  5. package/dist/lib/cli.d.ts +1 -0
  6. package/dist/lib/cli.js +5521 -0
  7. package/dist/lib/cli.js.map +7 -0
  8. package/dist/lib/editor/api.d.ts +42 -0
  9. package/dist/lib/editor/app.d.ts +13 -0
  10. package/dist/lib/editor/atlas-detect.d.ts +28 -0
  11. package/dist/lib/editor/atlas-panel.d.ts +1 -0
  12. package/dist/lib/editor/atlas.d.ts +39 -0
  13. package/dist/lib/editor/gizmo-math.d.ts +36 -0
  14. package/dist/lib/editor/gizmos.d.ts +185 -0
  15. package/dist/lib/editor/layers.d.ts +1 -0
  16. package/dist/lib/editor/library.d.ts +3 -0
  17. package/dist/lib/editor/panels.d.ts +26 -0
  18. package/dist/lib/editor/props.d.ts +19 -0
  19. package/dist/lib/editor/server.d.ts +11 -0
  20. package/dist/lib/editor/stage.d.ts +222 -0
  21. package/dist/lib/editor/store.d.ts +1053 -0
  22. package/dist/lib/editor/timeline-layout.d.ts +64 -0
  23. package/dist/lib/editor/timeline.d.ts +45 -0
  24. package/dist/lib/editor-entry.d.ts +2 -0
  25. package/dist/lib/editor-entry.js +5490 -0
  26. package/dist/lib/editor-entry.js.map +7 -0
  27. package/dist/lib/harness.js +51012 -0
  28. package/dist/lib/ktx2.d.ts +15 -0
  29. package/dist/lib/mcp-server.d.ts +2 -0
  30. package/dist/lib/preview/harness.d.ts +16 -0
  31. package/dist/lib/preview/render-preview.d.ts +27 -0
  32. package/dist/lib/preview/viewer.d.ts +1 -0
  33. package/dist/lib/rig-anim.d.ts +109 -0
  34. package/dist/lib/rig-api.d.ts +26 -0
  35. package/dist/lib/rig-atlas.d.ts +20 -0
  36. package/dist/lib/rig-check.d.ts +45 -0
  37. package/dist/lib/rig-constraints.d.ts +59 -0
  38. package/dist/lib/rig-deform.d.ts +27 -0
  39. package/dist/lib/rig-format.d.ts +5036 -0
  40. package/dist/lib/rig-history.d.ts +21 -0
  41. package/dist/lib/rig-import-layers.d.ts +32 -0
  42. package/dist/lib/rig-io.d.ts +9 -0
  43. package/dist/lib/rig-mesh-image.d.ts +2 -0
  44. package/dist/lib/rig-mesh.d.ts +143 -0
  45. package/dist/lib/rig-path.d.ts +101 -0
  46. package/dist/lib/rig-presets.d.ts +101 -0
  47. package/dist/lib/rig-queue.d.ts +2 -0
  48. package/dist/lib/rig-runtime.d.ts +70 -0
  49. package/dist/lib/rig-state.d.ts +64 -0
  50. package/dist/lib/rig-symbol.d.ts +60 -0
  51. package/dist/lib/rig-template-library.d.ts +3 -0
  52. package/dist/lib/rig-templates.d.ts +46 -0
  53. package/dist/lib/rig-tools.d.ts +376 -0
  54. package/dist/lib/runtime.d.ts +9 -0
  55. package/dist/lib/runtime.js +1584 -0
  56. package/dist/lib/runtime.js.map +7 -0
  57. package/dist/lib/spine-import.d.ts +68 -0
  58. package/dist/lib/tools.d.ts +2 -0
  59. package/dist/lib/tools.js +5242 -0
  60. package/dist/lib/tools.js.map +7 -0
  61. package/editor.html +3 -0
  62. package/package.json +96 -0
@@ -0,0 +1,15 @@
1
+ export interface Ktx2Info {
2
+ width: number;
3
+ height: number;
4
+ levels: number;
5
+ hasAlpha: boolean;
6
+ uastc: boolean;
7
+ }
8
+ /** Transcode level 0 of a KTX2 texture to RGBA8. */
9
+ export declare function ktx2ToRgba(data: Uint8Array): Promise<Ktx2Info & {
10
+ rgba: Uint8Array;
11
+ }>;
12
+ /** Transcode a KTX2 texture to a PNG buffer. */
13
+ export declare function ktx2ToPng(data: Uint8Array): Promise<Ktx2Info & {
14
+ png: Buffer;
15
+ }>;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,16 @@
1
+ export interface RenderOptions {
2
+ animation?: string;
3
+ times: number[];
4
+ overlayBones?: boolean;
5
+ background?: string;
6
+ scale?: number;
7
+ sheetColumns?: number;
8
+ onionSkin?: boolean;
9
+ region?: [number, number, number, number];
10
+ }
11
+ export interface RenderResult {
12
+ frames: string[];
13
+ sheet: string;
14
+ width: number;
15
+ height: number;
16
+ }
@@ -0,0 +1,27 @@
1
+ import { type RigDocument } from "../rig-format";
2
+ export interface PreviewOptions {
3
+ /** directory that asset.src paths are relative to */
4
+ assetsDir: string;
5
+ animation?: string;
6
+ /** explicit sample times, OR fps (+ optional count) evenly over the animation */
7
+ times?: number[];
8
+ fps?: number;
9
+ count?: number;
10
+ overlayBones?: boolean;
11
+ background?: string;
12
+ scale?: number;
13
+ sheetColumns?: number;
14
+ /** ghost the previous frame under each frame */
15
+ onionSkin?: boolean;
16
+ /** crop [x, y, w, h] in DOCUMENT pixels — zoom on a detail without spending tokens on the whole canvas */
17
+ region?: [number, number, number, number];
18
+ }
19
+ export interface PreviewResult {
20
+ frames: Buffer[];
21
+ sheet: Buffer;
22
+ times: number[];
23
+ width: number;
24
+ height: number;
25
+ }
26
+ export declare function closePreview(): Promise<void>;
27
+ export declare function renderPreview(doc: RigDocument, opts: PreviewOptions): Promise<PreviewResult>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,109 @@
1
+ /**
2
+ * rig-anim — pure animation math shared by the runtime, the checker, the importer and tests. No PixiJS.
3
+ *
4
+ * - easing + track sampling, Pose: Map<"target:id:prop", value>
5
+ * - 2D affine matrices with PixiJS layout (a b c d tx ty; x' = a·x + c·y + tx, y' = b·x + d·y + ty)
6
+ * - bone world transforms with shear and inherit modes, constraints (ik / transform / path) applied in `order`
7
+ * - attachment geometry in document space: region corners, skinned mesh vertices, lattice deformation
8
+ */
9
+ import type { RigDocument, Animation, Track, Bone, Attachment, RegionAttachment, MeshAttachment, PathAttachment } from "./rig-format";
10
+ export type EaseSpec = Track["keys"][number]["ease"];
11
+ export declare function ease(spec: EaseSpec): (t: number) => number;
12
+ export type Val = number | string | null | number[] | string[];
13
+ /** key: "bone:id:prop" | "slot:id:prop" | "deform:id:prop" | "ik:id:prop" | "transform:id:prop" | "path:id:prop" | "drawOrder:order:order" */
14
+ export type Pose = Map<string, Val>;
15
+ export declare const pk: (target: string, id: string, prop: string) => string;
16
+ export declare function sample(track: Track, t: number): Val;
17
+ export declare function poseOf(anim: Animation, t: number, out?: Pose): Pose;
18
+ /** Crossfade: numbers (and number arrays) interpolate toward `to` (or rest when absent there); discrete values hold until w = 1. */
19
+ export declare function blendPoses(from: Pose, to: Pose, w: number, restOf: (key: string) => Val): Pose;
20
+ /** Setup value of a pose key. */
21
+ export declare function restValue(doc: RigDocument, key: string): Val;
22
+ /** "#rrggbbaa" → [r, g, b, a] in 0..1 */
23
+ export declare const colorToArray: (c: string) => number[];
24
+ /** Numeric lattice deform params of one attachment present in the pose, or undefined when it has none. */
25
+ export declare function deformParams(pose: Pose, attachmentId: string): Record<string, number> | undefined;
26
+ export interface Affine {
27
+ a: number;
28
+ b: number;
29
+ c: number;
30
+ d: number;
31
+ tx: number;
32
+ ty: number;
33
+ }
34
+ /** translate · rotate(deg, clockwise in Y-down) · shear · scale — PixiJS setTransform semantics with shear as axis angles */
35
+ export declare function affineOf(x: number, y: number, rotationDeg: number, sx: number, sy: number, shearX?: number, shearY?: number): Affine;
36
+ /** parent ∘ local (apply local first, then parent) — PixiJS Matrix.append */
37
+ export declare function mul(p: Affine, l: Affine): Affine;
38
+ export declare const apply: (m: Affine, x: number, y: number) => [number, number];
39
+ export declare function invert(m: Affine): Affine;
40
+ /** rotation of the x axis of an affine, degrees */
41
+ export declare const rotationOf: (m: Affine) => number;
42
+ /**
43
+ * Where a world matrix puts a bone, which way its x axis points, and how long its axes are — the inverse of
44
+ * `affineOf` for everything except shear, which cannot be recovered from the axes alone (a sheared y axis is
45
+ * reported by its length, and `angle` follows the x axis only). Reading a posed bone goes through here so the
46
+ * numbers an agent gets are the numbers the runtime drew.
47
+ */
48
+ export declare function decompose(m: Affine): {
49
+ x: number;
50
+ y: number;
51
+ angle: number;
52
+ scaleX: number;
53
+ scaleY: number;
54
+ };
55
+ export interface BoneState {
56
+ /** effective local values (setup + pose + constraint adjustments) */
57
+ x: number;
58
+ y: number;
59
+ rotation: number;
60
+ scaleX: number;
61
+ scaleY: number;
62
+ shearX: number;
63
+ shearY: number;
64
+ world: Affine;
65
+ }
66
+ export interface Skeleton {
67
+ doc: RigDocument;
68
+ pose: Pose;
69
+ bones: Map<string, BoneState>;
70
+ /** attachment shown per slot (pose or setup), null = hidden */
71
+ attachment: Map<string, Attachment | null>;
72
+ }
73
+ /** world transform of one bone from its effective local values and its parent's world transform, honouring `inherit` */
74
+ export declare function boneWorldOf(bone: Bone, s: Omit<BoneState, "world">, parent: Affine | undefined): Affine;
75
+ export declare function boneOrder(doc: RigDocument): Bone[];
76
+ /** Full skeleton evaluation for a pose: bone locals, constraints in order, world transforms, shown attachments. */
77
+ export declare function evaluate(doc: RigDocument, pose: Pose): Skeleton;
78
+ /** Bone world transforms for a pose (constraints applied). */
79
+ export declare function boneWorld(doc: RigDocument, pose: Pose): Map<string, Affine>;
80
+ /** world-space control points of a path attachment (2 numbers per vertex) */
81
+ export declare function pathWorldVertices(skel: Skeleton, slotId: string, att: PathAttachment): number[];
82
+ /** path length: `lengths[i]` is the length up to the end of curve i; an open path stores one extra entry */
83
+ export declare function pathLength(vertexCount: number, closed: boolean, lengths: number[]): number;
84
+ /**
85
+ * Sample positions and tangents along a path made of cubic bezier curves through the attachment vertices
86
+ * (vertex layout: [c_prev, p, c_next] triples; curve i runs p_i → c_next_i → c_prev_{i+1} → p_{i+1}).
87
+ */
88
+ /**
89
+ * Points along a path attachment (document space). `positions` are absolute distances along the path (or fractions of
90
+ * its length when `percent`). With `constantSpeed` the length of the posed curve is measured (4 chords per curve for
91
+ * the total, 10 chords inside the curve that holds the position); otherwise the stored setup `lengths` and the raw
92
+ * curve parameter are used. Closed paths wrap; positions beyond an open path continue along its end tangents.
93
+ * `angle` is the tangent direction in degrees.
94
+ */
95
+ export declare function samplePath(points: number[], closed: boolean, lengths: number[], constantSpeed: boolean, positions: number[], percent: boolean): {
96
+ x: number;
97
+ y: number;
98
+ angle: number;
99
+ }[];
100
+ /** skinned or bone-local vertices of a mesh/path attachment in document space, deform offsets applied */
101
+ export declare function attachmentWorldVertices(skel: Skeleton, slotId: string, att: MeshAttachment | PathAttachment): number[];
102
+ /** image-local (centre-relative) → document matrix for a region attachment */
103
+ export declare function regionMatrix(skel: Skeleton, slotId: string, att: RegionAttachment): Affine;
104
+ export declare function regionSize(doc: RigDocument, att: RegionAttachment): [number, number];
105
+ /**
106
+ * Outline of a slot's shown attachment in document space: region → `samplesPerEdge` points per edge clockwise
107
+ * from the top-left (lattice deform applied), mesh → hull vertices (or all), path/hidden → undefined.
108
+ */
109
+ export declare function slotOutline(doc: RigDocument, pose: Pose, slotId: string, samplesPerEdge?: number, skel?: Skeleton): [number, number][] | undefined;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * rig-api — the tool registry. MCP (stdio), the CLI and the editor's HTTP server all register these same tools,
3
+ * so a human in the editor and an agent over MCP perform identical operations with identical history.
4
+ *
5
+ * Each tool reads `rig.json`, applies, writes back. Stateless per call: agents can crash/retry freely; the file
6
+ * is the state. Every mutation first snapshots the previous file into `.rig-history/` (rig_undo / rig_diff) and
7
+ * answers with what changed; structural tools also return the compact rig summary.
8
+ */
9
+ import { z } from "zod";
10
+ import { RigDocument } from "./rig-format";
11
+ export interface ToolResult {
12
+ text: string;
13
+ image?: Buffer;
14
+ doc?: RigDocument;
15
+ isError?: boolean;
16
+ }
17
+ /** `input` is the BUILT schema, not the raw shape: see `tool` below for why every caller has to share this one object */
18
+ export interface ToolDef {
19
+ name: string;
20
+ description: string;
21
+ input: z.AnyZodObject;
22
+ run(args: Record<string, unknown>): Promise<ToolResult>;
23
+ }
24
+ export declare const tools: ToolDef[];
25
+ export declare function callTool(name: string, args: unknown): Promise<ToolResult>;
26
+ export declare const closeTools: () => Promise<void>;
@@ -0,0 +1,20 @@
1
+ import type { RigDocument } from "./rig-format";
2
+ export interface Rect {
3
+ id: string;
4
+ width: number;
5
+ height: number;
6
+ }
7
+ export interface Packed {
8
+ width: number;
9
+ height: number;
10
+ frames: Map<string, [number, number, number, number]>;
11
+ }
12
+ export interface PackOptions {
13
+ /** gap between frames in px (default 2); never less than 2·extrude */
14
+ padding?: number;
15
+ /** px of edge replication into the gutter (default 1) */
16
+ extrude?: number;
17
+ maxSize?: number;
18
+ }
19
+ export declare function packRects(rects: Rect[], opts?: PackOptions): Packed;
20
+ export declare function buildAtlas(doc: RigDocument, assetsDir: string, outDir: string, opts?: PackOptions): Promise<RigDocument>;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * rig-check — cheap self-critique for agents, computed from the document alone (no browser).
3
+ *
4
+ * Findings are hints, not a pass/fail gate: `rest_overlap` is normal for cut-out characters,
5
+ * `out_of_canvas` may be intended for a jump. `deform_flip` and `mesh_fold` are the real errors (folded mesh/lattice);
6
+ * `weights_sum` flags skinned-mesh vertices whose influence weights don't add to 1.
7
+ *
8
+ * `mesh_fold` is graded by how much of the mesh folds — the folded triangles' rest area over the mesh's total rest
9
+ * area, at the worst sampled time. A dense mesh bent hard at a joint almost always pinches one hairline triangle
10
+ * somewhere; that is a `warn`, not something to stop for. `error` is reserved for a fold big enough to see
11
+ * (≥ `FOLD_ERROR_RATIO` of the mesh), which is what a torn limb or a collapsed silhouette looks like.
12
+ *
13
+ * Constraints get four of their own: `constraint_dead` (every mix is 0 at rest and no track lifts one — the solver
14
+ * skips it), `constraint_cycle` (the target is a bone the constraint drives, or hangs off one: it reads what it
15
+ * writes — an error), `ik_unreachable` (the target sits beyond the chain's reach for most of an animation, so the
16
+ * limb hangs straight instead of following) and `path_missing` (a path constraint whose target slot never shows a
17
+ * path attachment — an error).
18
+ */
19
+ import { type RigDocument } from "./rig-format";
20
+ export interface Finding {
21
+ level: "error" | "warn" | "info";
22
+ code: string;
23
+ /** slot / track / asset the finding is about */
24
+ subject: string;
25
+ message: string;
26
+ animation?: string;
27
+ time?: number;
28
+ }
29
+ export interface CheckOptions {
30
+ /** only this animation (plus the rest pose) */
31
+ animation?: string;
32
+ /** sampling rate for outlines (default 30) and for the fold check (default 60) */
33
+ fps?: number;
34
+ deformFps?: number;
35
+ /** rest_overlap threshold as a fraction of the smaller box (default 0.6) */
36
+ overlap?: number;
37
+ /** px of allowed overflow before out_of_canvas fires (default 1) */
38
+ margin?: number;
39
+ }
40
+ export declare function checkRig(doc: RigDocument, opts?: CheckOptions): Finding[];
41
+ /** One-line count plus the findings — appended to preview results and returned by rig_check.
42
+ * A single noisy code (e.g. mesh_fold across 100 meshes) is capped at 5 lines so it can't crowd out every
43
+ * other kind of finding within `max`; the rest fold into one "… N more <code>" line, then the overall `max`
44
+ * still applies on top of that. */
45
+ export declare function summarize(findings: Finding[], max?: number): string;
@@ -0,0 +1,59 @@
1
+ /**
2
+ * rig-constraints — pure helpers for authoring constraints: which bones a constraint drives, the 1–2 bone chain
3
+ * behind a limb, the bend sign that reproduces a pose, IK reach, and path geometry from anchor points.
4
+ * The solvers themselves live in rig-anim.ts and are not touched here. No node:*, no DOM.
5
+ */
6
+ import { type RigDocument, type IkConstraint } from "./rig-format";
7
+ import { type Pose, type Skeleton } from "./rig-anim";
8
+ export type Pt = [number, number];
9
+ /** bone id → ids of the constraints that write that bone, in the order the solver applies them */
10
+ export declare function drivenBones(doc: RigDocument): Map<string, string[]>;
11
+ /**
12
+ * A constraint's property at one moment: the keyed value, else the document's. That is the read the solvers make
13
+ * to decide whether they run at all (`cnum` in rig-anim.ts), so anything asking "is this constraint live here?"
14
+ * has to make the same one — hence one exported copy rather than a fourth private one.
15
+ */
16
+ export declare const mixAt: (pose: Pose, kind: string, id: string, prop: string, rest: number) => number;
17
+ /**
18
+ * The constraint that owns a bone's transform in this pose, or undefined when the bone is really editable there.
19
+ * The LAST constraint in solver order wins (it writes last), and one counts only while it is actually mixed IN —
20
+ * the solvers' own early-outs, listed once in `MIX_PROPS`. A mixed-out constraint therefore blocks nothing: at
21
+ * that frame the solver skips it and whatever wrote before it stands.
22
+ * `Stage.driverOf` forwards to this function over the editor's own pose signal — there is no second copy left.
23
+ */
24
+ export declare function driverAt(doc: RigDocument, pose: Pose, bone: string): {
25
+ kind: "ik" | "transform" | "path";
26
+ id: string;
27
+ target: string;
28
+ } | undefined;
29
+ /** [parent, bone] when the parent has exactly one child (an unambiguous limb), else [bone] */
30
+ export declare function ikChainFor(doc: RigDocument, bone: string): string[];
31
+ /** world point at the far end of the chain's last bone (its `length` along its x axis) */
32
+ export declare function chainEnd(skel: Skeleton, chain: string[]): Pt;
33
+ /**
34
+ * `bendPositive` for a two-bone chain: the sign of the cross product of the chain's two segments as they are posed
35
+ * now — parent origin → child origin, then child origin → the chain's tip. That is the triangle the two-bone solver
36
+ * works in (`bendDir` picks which side of it the joint falls on), so the sign matches it even when the parent is
37
+ * sheared or its child hangs off its x axis, where "the parent's x axis" would not.
38
+ * A straight chain (cross ≈ 0) answers `true`, matching Spine's default.
39
+ * A chain whose last bone has `length: 0` has no measurable bend either (the tip coincides with the bone's own
40
+ * origin, so the cross product is always exactly 0) and likewise answers `true`.
41
+ */
42
+ export declare function bendSignFor(skel: Skeleton, chain: string[]): boolean;
43
+ /** distance from the chain root to the target and the chain's maximum reach, both in world px */
44
+ export declare function ikReach(skel: Skeleton, c: IkConstraint): {
45
+ distance: number;
46
+ reach: number;
47
+ };
48
+ /** anchor points of a path attachment in document space (every third vertex, starting at index 1) */
49
+ export declare const pathAnchors: (world: number[]) => Pt[];
50
+ /**
51
+ * Anchor points → the format's `[cPrev, anchor, cNext]` triples. Control points come from Catmull-Rom tangents
52
+ * ((next − prev) / 6), which makes the curve pass through every anchor with C1 continuity; the ends of an open
53
+ * path use the single available neighbour. Coordinates are converted into the slot bone's space.
54
+ */
55
+ export declare function pathFromPoints(skel: Skeleton, slotId: string, points: Pt[], closed: boolean): {
56
+ vertices: number[];
57
+ closed: boolean;
58
+ lengths: number[];
59
+ };
@@ -0,0 +1,27 @@
1
+ /**
2
+ * rig-deform — 3×3 control-grid deformer for a slot's attachment (pure math, no PixiJS).
3
+ *
4
+ * Control points live on an interpolating biquadratic (Lagrange) patch over the image:
5
+ * rows r=0..2 at v=0,0.5,1 of the height (top→bottom), cols c=0..2 at u=0,0.5,1 of the width.
6
+ * Each control point carries an offset (dx, dy) in image pixels. With zero offsets the patch is the
7
+ * identity, and moving control point (r,c) by d moves the surface at that point by exactly d.
8
+ *
9
+ * Named params are dimensionless fractions of the image size (see spec §1); raw `p<r><c>x|y` are pixels.
10
+ * All contributions add.
11
+ */
12
+ export declare const DEFORM_NAMED: readonly ["bulge", "bend", "sway", "squash"];
13
+ export declare const DEFORM_PROP_RE: RegExp;
14
+ /** |value| bound per named param. bulge/squash reach a degenerate (zero-area) patch at 1, hence 0.9. */
15
+ export declare const DEFORM_BOUNDS: Record<(typeof DEFORM_NAMED)[number], number>;
16
+ export interface Pivot {
17
+ x: number;
18
+ y: number;
19
+ }
20
+ /** Named params + raw offsets → 18 numbers [dx00, dy00, dx01, dy01, …] row-major by (r*3+c). */
21
+ export declare function controlOffsets(params: Record<string, number>, w: number, h: number, pivot: Pivot, out?: Float64Array): Float64Array;
22
+ /** Patch offset at normalized image coords (u, v) ∈ [0,1]². */
23
+ export declare function evalPatch(offsets: ArrayLike<number>, u: number, v: number): [number, number];
24
+ /** n×n render vertices (row-major, x fastest — PlaneGeometry order), pivot baked in, image-local pixels. */
25
+ export declare function gridPositions(offsets: ArrayLike<number>, w: number, h: number, pivot: Pivot, n: number, out?: Float32Array): Float32Array;
26
+ /** Minimum Jacobian determinant of (u,v)→image map over a sample grid, normalized so identity = 1. ≤ 0 means a fold. */
27
+ export declare function minJacobian(offsets: ArrayLike<number>, w: number, h: number, samples?: number): number;