@melite/3d-img-to-mesh 0.1.4-alpha → 0.1.5-pre-alpha

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 ADDED
@@ -0,0 +1,38 @@
1
+ ---
2
+ description: Image-to-mesh card that boards three mesh families — pixal3d, trellis2-native, and transfer_rig — plus the mesh studio client.
3
+ kind: package-library
4
+ ---
5
+
6
+ # @melite/3d-img-to-mesh
7
+
8
+ `@melite/3d-img-to-mesh` is the image-to-mesh card. One card serves three families, each with its own declared action: `pixal3d` and `trellis2-native` run the `mesh` action (image in, mesh out); `transfer_rig` runs `transfer` (rig transfers between two GLBs). The cardPackages SSOT composes the card from `./card`; the browser studio rides `./client`.
9
+
10
+ ## Contract
11
+
12
+ - `./card` — the card definition (`id: 'img-to-mesh'`). Family dispatch keys on `model.family ?? model.id`; an unbound family refuses loudly. Per-family requirements: pixal3d needs the `ComfyUI-MoGe` pack, transfer_rig needs `melite-autorig-nodes`, trellis2-native needs none; the card-level `requires` is the union. Flow seats: `input_image` (image), `rigged_glb` and `target_glb` (mesh) in; mesh out, bound to `Save3DAdvanced.0` or `SaveRiggedModel.0` per action. Autofill literals (RemeshMesh band/project_back, ImageCropToMask background/grow_mask, MoGeInference apply_mask/batch_size/force_projection/fov_x_degrees) ride the compose; `remesh_qef`, `remesh_drop_inverted`, `remesh_drop_enclosed`, and `remesh_fix_poles` are card params.
13
+ - `./client` — `ImgToMeshStudio`, a DeclarativeStudio registration exposing the `input` and `generation` stages with the mesh preview; the plugin injects into `slots`.
14
+ - `.` — the row-mounted host face; it registers nothing.
15
+ - `./package.json` — the manifest.
16
+
17
+ ## Model Experience
18
+
19
+ ### Request context and condition
20
+
21
+ A run conditions the mesh graph only when the card composes; the package ships no agent tool face.
22
+
23
+ #### What the model sees
24
+
25
+ The active family's mesh model receives `input_image` plus the gated card params; the transfer action receives both GLBs.
26
+
27
+ #### Token effect
28
+
29
+ zero-direct — the package contributes no prompt or schema to any language-model context.
30
+
31
+ #### KV Cache effect
32
+
33
+ independent — nothing here appends to or reshapes a session cache.
34
+
35
+ ## Known Limitations and Deferred Work
36
+
37
+ - **Per-family surfaces differ** — only pixal3d and transfer_rig carry pack requirements today; a new family must declare both its action and its slice.
38
+ - **Studio exposure is fixed** — `ImgToMeshStudio` folds the input and generation stages; other stages are not exposed yet.
package/lib/card.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- import type { Context } from '@deepseek-ai/cordis';
2
- import type { ModelFacts } from '@melite/comfyui-card-kit/facts';
3
- import type { GraphBuilder } from '@melite/comfyui-card-kit/graph';
1
+ import type { Context } from '@melite/comfyui-card-kit/card-definition';
2
+ import { type ActionBinding as Binding } from '@melite/comfyui-card-kit';
4
3
  export declare const inject: string[];
5
4
  export declare const identity: {
6
5
  label: string;
@@ -8,7 +7,6 @@ export declare const identity: {
8
7
  genre: string;
9
8
  icon: string;
10
9
  };
11
- export type Binding = (p: Record<string, unknown>, model: ModelFacts, g: GraphBuilder, runId: string) => void;
12
10
  export declare const ACTION_BINDINGS: Record<string, Binding>;
13
11
  export declare function apply(ctx: Context): void;
14
12
  //# sourceMappingURL=card.d.ts.map
package/lib/card.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import z from '@deepseek-ai/schemastery';
2
- import { declaredAction, instantiateAction, MESH_RESOLUTIONS, MESH_BG_MODES, MESH_PIXAL_FOVS, MESH_ATLAS_SIZES, MESH_AO_SIZES, MESH_NORMAL_SIZES } from '@melite/comfyui-card-kit';
2
+ import { declaredAction, instantiateAction, MESH_RESOLUTIONS, MESH_PIXAL_FOVS, MESH_ATLAS_SIZES, MESH_AO_SIZES, MESH_NORMAL_SIZES } from '@melite/comfyui-card-kit';
3
3
  import { DECL as pixal3dDecl } from '@melite/models-pixal3d';
4
4
  import { DECL as trellis2NativeDecl } from '@melite/models-trellis2-native';
5
5
  import { DECL as transferRigDecl } from '@melite/models-transfer_rig';
6
6
  import { SAMPLERS, SCHEDULERS, vocabulary } from '@melite/comfyui-card-kit/vocab';
7
7
  import { bag } from '@melite/contracts/extraKeys';
8
- import { gatedResolve } from '@melite/comfyui-cordis';
8
+ import { ComposeRefusal } from '@melite/comfyui-card-kit/errors';
9
+ import { seedExtra } from '@melite/comfyui-card-kit/fields';
10
+ import { callableSchema, gatedResolve } from '@melite/comfyui-card-kit/admission';
9
11
  const schema = z.object({
10
12
  // Ride keys (no .default — the compose-door cascade overlays model
11
13
  // defaults, then explicit params): input_image is required; the
@@ -14,16 +16,15 @@ const schema = z.object({
14
16
  // lift call never names them and a rig call names both. Bare
15
17
  // z.string() is the image-gen prompt precedent (optional at parse,
16
18
  // refused loud at compose).
17
- input_image: z.string().role('path').description("Source image").extra('extra', bag({ order: 0, group: "input", columns: 1, tooltip: "One clear object, tight framing. Background is removed automatically (birefnet) unless bg_removal=off.", required: true, families: ['pixal3d', 'trellis2-native'], wtype: 'image', })),
19
+ input_image: z.string().role('path').description("Source image").extra('extra', bag({ order: 0, group: "input", columns: 1, tooltip: "One clear object, tight framing — the lane crops it to a square and conditions on it directly.", required: true, families: ['pixal3d', 'trellis2-native'], wtype: 'image', })),
18
20
  rigged_glb: z.string().role('path').description("Rigged source GLB").extra('extra', bag({ order: 0, group: "input", columns: 1, tooltip: "The SOMA-rigged clean mesh — JOINTS_0/WEIGHTS_0 + armature. The rig donor.", families: ['transfer_rig'], wtype: 'mesh' })),
19
21
  target_glb: z.string().role('path').description("Target GLB").extra('extra', bag({ order: 1, group: "input", columns: 1, tooltip: "The clothed mesh — geometry + textures, no rig. Receives the rig.", families: ['transfer_rig'], wtype: 'mesh' })),
20
- seed: z.number().description("Seed").step(1).extra('extra', bag({ order: 1, group: "input", width: 1, tooltip: "Same seed + image = same mesh take.", families: ['pixal3d', 'trellis2-native'] })),
22
+ seed: z.number().description("Seed").step(1).extra('extra', bag(seedExtra({ order: 1, group: 'input', width: 1, tooltip: 'Same seed + image = same mesh take.', families: ['pixal3d', 'trellis2-native'] }))),
21
23
  // Select knobs coerce wire strings at compose (the skin map_size
22
24
  // precedent) — enum hints ride extra.options, never validation.
23
25
  resolution: vocabulary(MESH_RESOLUTIONS).description("Resolution").extra('extra', bag({ order: 0, group: "generation", width: 1, tooltip: "Upsample target (the live node accepts 1024–2048; the family routes serve 1024 and 1536). All tiers run the full official chain — upsample + both texture passes + remesh tail.", families: ['pixal3d', 'trellis2-native'], wtype: 'select' })),
24
26
  steps: z.number().description("Steps").min(4).max(60).step(1).extra('extra', bag({ order: 1, group: "generation", width: 1, tooltip: "STRUCTURE stage steps (the lift). Shape + texture stages ride their own knobs in the Stage section.", families: ['pixal3d', 'trellis2-native'], wtype: 'number' })),
25
27
  cfg: z.number().description("CFG").min(1).max(15).step(0.5).extra('extra', bag({ order: 2, group: "generation", width: 1, tooltip: "Structure-stage guidance. 7.5 is the official template calibration (2026-09-06: the 3.0 default sampled the coarse shape at under half guidance — blobby trash out of the box). Lower runs looser.", families: ['pixal3d', 'trellis2-native'] })),
26
- bg_removal: vocabulary(MESH_BG_MODES).description("Background removal").extra('extra', bag({ order: 3, group: "generation", width: 1, tooltip: "auto/on: birefnet cuts the background (recommended). off: feed a pre-cleaned or alpha-cut image straight to conditioning.", families: ['pixal3d', 'trellis2-native'], wtype: 'select' })),
27
28
  camera_fov: vocabulary(MESH_PIXAL_FOVS).description("Camera FoV").extra('extra', bag({ order: 4, group: "generation", width: 1, tooltip: "Pixal3D only — per-image horizontal FoV feeding the camera transform matrix. auto: MoGeInference estimates from the source image (recommended); a literal degree value skips MoGe (operator-vouched camera, e.g. calibrated).", families: ['pixal3d'], wtype: 'select' })),
28
29
  shape_steps: z.number().description("Shape steps").min(4).max(60).step(1).extra('extra', bag({ order: 0, group: "stage", width: 1, tooltip: "Shape-stage steps. 20 is the official template calibration.", families: ['pixal3d', 'trellis2-native'], wtype: 'number' })),
29
30
  shape_cfg: z.number().description("Shape CFG").min(1).max(15).step(0.5).extra('extra', bag({ order: 1, group: "stage", width: 1, tooltip: "Shape-stage guidance. 7.5 is the official template calibration.", families: ['pixal3d', 'trellis2-native'] })),
@@ -61,12 +62,7 @@ const schema = z.object({
61
62
  // never a declared knob, and compose never reads it: prefixes are
62
63
  // family constants below).
63
64
  });
64
- /** The schema's callable face — ONE cast serving both seams (the
65
- * registration's schema carrier and the compose strict resolve's
66
- * judge): schemastery schemas are callable (Schema.resolve) but
67
- * carry a typed data parameter, while both card-seam consumers
68
- * take unknown. */
69
- const schemaFn = schema;
65
+ const schemaFn = callableSchema(schema);
70
66
  export const inject = ['comfyui'];
71
67
 
72
68
  // identity ring; the card owns its label/description/genre/icon).
@@ -76,6 +72,11 @@ export const identity = {
76
72
  genre: '3d',
77
73
  icon: 'box',
78
74
  };
75
+ // THE FAMILY BINDINGS (the atom vocabulary, stroke 3): every
76
+ // boarded family's declared action, keyed by the row's family
77
+ // address — the id-switch dispatch died with them. A family-less
78
+ // row (the declared fallback) rides the legacy lane arms below —
79
+ // never a silent second copy.
79
80
  export const ACTION_BINDINGS = {
80
81
  [pixal3dDecl.id]: (p, model, g, runId) => void instantiateAction(declaredAction(pixal3dDecl, 'mesh'), p, model, g, runId),
81
82
  [trellis2NativeDecl.id]: (p, model, g, runId) => void instantiateAction(declaredAction(trellis2NativeDecl, 'mesh'), p, model, g, runId),
@@ -146,6 +147,20 @@ export function apply(ctx) {
146
147
  // their rows), fills defaults, passes undeclared keys through
147
148
  // inert. The composer's reads below are reads of the GATED doc.
148
149
  const doc = gatedResolve('img-to-mesh', schemaFn, ['model', 'input_image', 'rigged_glb', 'target_glb'], p);
150
+ // THE PAIRED GLB LANE (round-22 compose audit Q4b, EXHAUSTIVE-WHEN):
151
+ // rigged_glb and target_glb are one paired transfer lane — both or
152
+ // neither, on EVERY family. The lift arms ignore the pair, so a
153
+ // mixed state composed fine there and the producer walk then
154
+ // selected no output at all: zero outputs, silently. The mixed
155
+ // state refuses here, before any arm; the producer predicates
156
+ // stay exclusive on the states that remain reachable.
157
+ const riggedSet = String(doc.rigged_glb ?? '').trim() !== '';
158
+ const targetSet = String(doc.target_glb ?? '').trim() !== '';
159
+ if (riggedSet !== targetSet) {
160
+ throw new ComposeRefusal('bad-value', `card 'img-to-mesh': rigged_glb and target_glb are one paired transfer lane — ` +
161
+ `${riggedSet ? "rigged_glb is set but target_glb is empty" : "target_glb is set but rigged_glb is empty"}; ` +
162
+ `set both for the rig transfer, or neither for the image-to-mesh lift`);
163
+ }
149
164
  // The arm IS the family's declared action (runId rides the
150
165
  // signature; prefixes are family constants, not run-scoped,
151
166
  // not knobs).
package/lib/client.js CHANGED
@@ -20,14 +20,30 @@ window.__ModuleLoader__.load({
20
20
 
21
21
 
22
22
 
23
+
24
+
25
+
26
+
23
27
  const SURFACE = (0, _melite_card_base_client.defineStudioDeclaration)({
24
28
  model: "img-to-mesh",
25
29
  expose: ["input", "generation"],
26
30
  folds: {
27
- stage: "Stage passes",
28
- mesh: "Mesh",
29
- bake: "Bake maps",
30
- lab: "Lab (samplers & overrides)"
31
+ stage: {
32
+ title: "Stage passes",
33
+ icon: "branch"
34
+ },
35
+ mesh: {
36
+ title: "Mesh",
37
+ icon: "box"
38
+ },
39
+ bake: {
40
+ title: "Bake maps",
41
+ icon: "layers"
42
+ },
43
+ lab: {
44
+ title: "Lab (samplers & overrides)",
45
+ icon: "sliders"
46
+ }
31
47
  },
32
48
  preview: "mesh"
33
49
  });
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Context } from '@deepseek-ai/cordis';
1
+ import type { Context } from '@melite/comfyui-card-kit/card-definition';
2
2
  export declare const name = "@melite/3d-img-to-mesh";
3
3
  export declare const inject: string[];
4
4
  export declare function apply(_ctx: Context): void;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
- "version": "0.1.4-alpha",
2
+ "version": "0.1.5-pre-alpha",
3
3
  "license": "SSPL-1.0",
4
4
  "type": "module",
5
- "description": "the img-to-mesh card (the 3d lane) — one card one package: card.ts host face + ui/ studio + agents/ context",
5
+ "description": "the img-to-mesh card (the 3d lane) — one card one package: card.ts host face + agents/ context (no tool face, no ui/ — the view is constructed by @melite/card-base from the emission)",
6
6
  "exports": {
7
7
  ".": {
8
8
  "types": "./lib/index.d.ts",
@@ -20,15 +20,13 @@
20
20
  "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.1",
21
21
  "@deepseek-ai/schemastery": "3.18.4",
22
22
  "react": "^19.3.0",
23
- "@melite-plugin/melite-run-wire": "0.1.4-alpha",
24
- "@melite/comfyui-card-kit": "0.1.4-alpha",
25
- "@melite/comfyui-cordis": "0.1.4-alpha",
26
- "@melite/contracts": "0.1.4-alpha",
27
- "@melite/models-pixal3d": "0.1.4-alpha",
28
- "@melite/models-transfer_rig": "0.1.4-alpha",
29
- "@melite/models-trellis2-native": "0.1.4-alpha",
30
- "@melite/card-base": "0.1.4-alpha",
31
- "@melite-plugin/3d": "0.1.4-alpha"
23
+ "@melite-plugin/melite-run-wire": "0.1.5-pre-alpha",
24
+ "@melite/card-base": "0.1.5-pre-alpha",
25
+ "@melite/comfyui-card-kit": "0.1.5-pre-alpha",
26
+ "@melite/contracts": "0.1.5-pre-alpha",
27
+ "@melite/models-pixal3d": "0.1.5-pre-alpha",
28
+ "@melite/models-transfer_rig": "0.1.5-pre-alpha",
29
+ "@melite/models-trellis2-native": "0.1.5-pre-alpha"
32
30
  },
33
31
  "devDependencies": {
34
32
  "@testing-library/jest-dom": "*",