@melite/image-upscale-tools 0.1.4-alpha → 0.2.0-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/LICENSE +561 -457
- package/README.md +36 -0
- package/lib/card.d.ts +1 -1
- package/lib/card.js +27 -15
- package/package.json +14 -11
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Hidden upscale card running SeedVR2 over an input image, with consumed fragment arms for resize, pixel-upscale, RTX VSR, and concat.
|
|
3
|
+
kind: package-library
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @melite/image-upscale-tools
|
|
7
|
+
|
|
8
|
+
`@melite/image-upscale-tools` is the upscale card (`id: 'upscale-tools'`, stage row `generate`): SeedVR2-3B fp16 diffusion upscaling on a required `input_image`. It boards the `seedvr2-ema` family's declared `upscale` action and requires the `ComfyUI-SeedVR2_VideoUpscaler`, `ComfyUI-KJNodes`, and `Nvidia_RTX_Nodes_ComfyUI` packs. The package's single source module is the root face the cardPackages SSOT composes (`@melite/image-upscale-tools`); there is no tool or client face. The card is hidden from the sidebar (image order 16) and additionally serves the consumed tool fragments — `resize`, `pixel-upscale`, `rtx-vsr`, `concat`, and `input` — each with its own arm.
|
|
9
|
+
|
|
10
|
+
## Contract
|
|
11
|
+
|
|
12
|
+
- `.` — the card definition and registration (the root module carries `inject = ['comfyui']`). Schema: `input_image` (required, path); ride keys with hint-only ranges and NO defaults — `resolution` (256..2160), `max_resolution` (512..4096), `batch_size` (1..16), where the model row owns the values (1080/4096/1); and `seed` (default −1). There are NO `dit_model`/`vae_model` knobs — weights ride the lane's `unet`/`vae` inputs. The `rtx-vsr` arm is compose-truth only: it emits the graph, while execution requires the NVIDIA SDK stack. `admits: ['filename_prefix']`; `spells: ['input_image']` — a `$spell` value (the `$image` form) names a wired stage input that rides verbatim. Estate-file contract: a file param must exist at compose (absolute mount path); a linked upstream output arrives as an asset URL (`/v1/assets/runs/...`) and the submit-time uploader stages it, refusing loudly on a dead URL.
|
|
13
|
+
- `./package.json` — the manifest.
|
|
14
|
+
|
|
15
|
+
## Model Experience
|
|
16
|
+
|
|
17
|
+
### Request context and condition
|
|
18
|
+
|
|
19
|
+
A run conditions the upscale graph only when the card composes; no agent tool face ships.
|
|
20
|
+
|
|
21
|
+
#### What the model sees
|
|
22
|
+
|
|
23
|
+
SeedVR2 receives the staged image plus the gated resolution, batch, and seed values as graph inputs.
|
|
24
|
+
|
|
25
|
+
#### Token effect
|
|
26
|
+
|
|
27
|
+
zero-direct — the package contributes no prompt or schema to any language-model context.
|
|
28
|
+
|
|
29
|
+
#### KV Cache effect
|
|
30
|
+
|
|
31
|
+
independent — nothing here appends to or reshapes a session cache.
|
|
32
|
+
|
|
33
|
+
## Known Limitations and Deferred Work
|
|
34
|
+
|
|
35
|
+
- **rtx-vsr needs the NVIDIA SDK** — the arm composes anywhere but executes only where the RTX stack exists.
|
|
36
|
+
- **No dit/vae knobs** — weight selection rides the model row; a card-level override is not declared.
|
package/lib/card.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Context } from '@
|
|
1
|
+
import type { Context } from '@melite/comfyui-card-kit/card-definition';
|
|
2
2
|
import type { ModelFacts } from '@melite/comfyui-card-kit/facts';
|
|
3
3
|
import type { GraphBuilder } from '@melite/comfyui-card-kit/graph';
|
|
4
4
|
export declare const ACTION_BINDINGS: Record<string, (p: Record<string, unknown>, model: ModelFacts, g: GraphBuilder, runId: string) => void>;
|
package/lib/card.js
CHANGED
|
@@ -2,10 +2,11 @@ import { existsSync, statSync } from 'node:fs';
|
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import z from '@deepseek-ai/schemastery';
|
|
4
4
|
import { declaredAction, instantiateAction } from '@melite/comfyui-card-kit';
|
|
5
|
-
import { resolveLinkedInput } from '@melite/comfyui-
|
|
5
|
+
import { resolveLinkedInput, runMediaPrefix } from '@melite/comfyui-card-kit/linked';
|
|
6
6
|
import { bag } from '@melite/contracts/extraKeys';
|
|
7
|
-
import { DECL as seedvr2Decl } from '@melite/models-
|
|
8
|
-
import {
|
|
7
|
+
import { DECL as seedvr2Decl } from '@melite/models-seedvr2-ema';
|
|
8
|
+
import { inputImageExtra, seedExtra } from '@melite/comfyui-card-kit/fields';
|
|
9
|
+
import { callableSchema, gatedResolve } from '@melite/comfyui-card-kit/admission';
|
|
9
10
|
// THE FAMILY BINDINGS (the atom vocabulary, stroke 3): the declared
|
|
10
11
|
// action composes; the legacy kit lane stays the declared fallback
|
|
11
12
|
// (byte-oracle + unbound-row safety). Keyed by OWNING FAMILY
|
|
@@ -17,10 +18,10 @@ export const ACTION_BINDINGS = {
|
|
|
17
18
|
},
|
|
18
19
|
};
|
|
19
20
|
const schema = z.object({
|
|
20
|
-
input_image: z.string().role('path').description("Input image").extra('extra', bag({
|
|
21
|
+
input_image: z.string().role('path').description("Input image").extra('extra', bag(inputImageExtra({ tooltip: 'The frame to restore. Absolute mount path.' }))),
|
|
21
22
|
// ride-the-model keys (ABSENT: no schema default — the
|
|
22
23
|
// compose-door cascade overlays model defaults, then explicit
|
|
23
|
-
// params): resolution/max_resolution/batch_size ride the
|
|
24
|
+
// params): resolution/max_resolution/batch_size ride the seedvr2-ema
|
|
24
25
|
// model row (1080/4096/1); seed rides -1 (model row carries 0,
|
|
25
26
|
// explicit wins — an explicit 42 rides the model row). RANGE RULE
|
|
26
27
|
|
|
@@ -30,18 +31,13 @@ const schema = z.object({
|
|
|
30
31
|
resolution: z.number().description("Target short side").min(256).max(2160).step(2).extra('extra', bag({ order: 0, group: "target", columns: 2, width: 1, tooltip: "1080 = FHD rail. SeedVR2 redraws detail at this size.", wtype: 'number' })),
|
|
31
32
|
max_resolution: z.number().description("Max resolution").min(512).max(4096).step(64).extra('extra', bag({ order: 1, group: "target", columns: 2, width: 1, tooltip: "The hard ceiling — inputs already past it pass through.", wtype: 'number' })),
|
|
32
33
|
batch_size: z.number().description("Batch size").min(1).max(16).step(1).extra('extra', bag({ order: 0, group: "run", width: 1, tooltip: "Video frames ride batches; images are batch 1.", wtype: 'number' })),
|
|
33
|
-
seed: z.number().description("Seed").step(1).default(-1).extra('extra', bag({ order: 1, group:
|
|
34
|
+
seed: z.number().description("Seed").step(1).default(-1).extra('extra', bag(seedExtra({ order: 1, group: 'run', width: 1 }))),
|
|
34
35
|
// NO dit_model/vae_model (card declares no such knobs — the
|
|
35
36
|
// weights ride lane_inputs.unet/vae; old drafts naming them still
|
|
36
37
|
// parse via the door's non-strict overlay but compose never reads
|
|
37
38
|
// them).
|
|
38
39
|
});
|
|
39
|
-
|
|
40
|
-
* registration's schema carrier and the compose strict resolve's
|
|
41
|
-
* judge): schemastery schemas are callable (Schema.resolve) but
|
|
42
|
-
* carry a typed data parameter, while both card-seam consumers
|
|
43
|
-
* take unknown. */
|
|
44
|
-
const schemaFn = schema;
|
|
40
|
+
const schemaFn = callableSchema(schema);
|
|
45
41
|
export const inject = ['comfyui'];
|
|
46
42
|
|
|
47
43
|
// identity ring; the card owns its label/description/genre/icon).
|
|
@@ -58,6 +54,17 @@ export const identity = {
|
|
|
58
54
|
'rtx-vsr is NVIDIA-SDK-only: the arm is compose-truth, execution needs the RTX stack',
|
|
59
55
|
],
|
|
60
56
|
};
|
|
57
|
+
/** The estate's own tree for the linked-input rewrite — the
|
|
58
|
+
* compose call's manifest, first entry (the queue's own root).
|
|
59
|
+
* A root-relative ref with no manifest refuses LOUD (there is no
|
|
60
|
+
* cwd guess to fall back on — J12 killed it). */
|
|
61
|
+
function estateRoot(estate) {
|
|
62
|
+
const first = estate?.stateRoots[0];
|
|
63
|
+
if (first === undefined || first === '') {
|
|
64
|
+
throw new Error("linked input needs the estate state root — compose with the queue seat's roots manifest (a root-relative asset URL cannot be resolved from the cwd; it never guesses)");
|
|
65
|
+
}
|
|
66
|
+
return first;
|
|
67
|
+
}
|
|
61
68
|
export function apply(ctx) {
|
|
62
69
|
ctx.effect(() => ctx.comfyui.registerCard({
|
|
63
70
|
id: 'upscale-tools',
|
|
@@ -82,7 +89,7 @@ export function apply(ctx) {
|
|
|
82
89
|
admits: ['filename_prefix'],
|
|
83
90
|
spells: ['input_image'],
|
|
84
91
|
schema: schemaFn,
|
|
85
|
-
compose(p, model, g, runId) {
|
|
92
|
+
compose(p, model, g, runId, estate) {
|
|
86
93
|
// THE SCHEMA GATE (the audio-trio admission precedent — the
|
|
87
94
|
// card's own declaration validates the last hop into the
|
|
88
95
|
// engine): schemastery walk enforces declared types + bounds
|
|
@@ -109,7 +116,12 @@ export function apply(ctx) {
|
|
|
109
116
|
// uploader fetches them); root-relative URLs rewrite to the
|
|
110
117
|
// runs-root mount path (same estate, verified NOW).
|
|
111
118
|
// Compile-time, never inference-time.
|
|
112
|
-
|
|
119
|
+
// J12: a root-relative asset URL resolves against the estate's
|
|
120
|
+
// config-named trees (the compose call's manifest — first tree
|
|
121
|
+
// is the queue's own root); every other spelling rides without
|
|
122
|
+
// a seat read. The retired env seam's cwd guess never returns.
|
|
123
|
+
const raw = String(doc.input_image).trim();
|
|
124
|
+
const ref = runMediaPrefix(raw) === '' ? raw : resolveLinkedInput(raw, estateRoot(estate));
|
|
113
125
|
doc.input_image = ref;
|
|
114
126
|
const lower = ref.toLowerCase();
|
|
115
127
|
if (!ref.startsWith('$') && !lower.startsWith('http://') && !lower.startsWith('https://')) {
|
|
@@ -122,7 +134,7 @@ export function apply(ctx) {
|
|
|
122
134
|
if (bound)
|
|
123
135
|
bound(doc, model, g, runId);
|
|
124
136
|
else {
|
|
125
|
-
throw new Error(`no declared action for family '${String(model.family ?? model.id)}' on the upscale-tools card — every boarded family (
|
|
137
|
+
throw new Error(`no declared action for family '${String(model.family ?? model.id)}' on the upscale-tools card — every boarded family (seedvr2-ema) composes its own declared segment; this address owns none`);
|
|
126
138
|
}
|
|
127
139
|
},
|
|
128
140
|
}));
|
package/package.json
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
3
|
-
"license": "
|
|
2
|
+
"version": "0.2.0-alpha",
|
|
3
|
+
"license": "AGPL-3.0-or-later",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "the upscale-tools card (the image lane) — one card one package: card.ts host face + ui/
|
|
5
|
+
"description": "the upscale-tools card (the image 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/card.d.ts",
|
|
9
9
|
"default": "./lib/card.js"
|
|
10
10
|
},
|
|
11
|
-
"./package.json": "./package.json"
|
|
11
|
+
"./package.json": "./package.json",
|
|
12
|
+
"./card": {
|
|
13
|
+
"types": "./lib/card.d.ts",
|
|
14
|
+
"default": "./lib/card.js"
|
|
15
|
+
}
|
|
12
16
|
},
|
|
13
17
|
"dependencies": {
|
|
14
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
15
|
-
"@melite/comfyui-card-kit": "0.
|
|
16
|
-
"@melite/
|
|
17
|
-
"@melite/
|
|
18
|
-
"@melite/models-seedvr2_ema": "0.1.4-alpha"
|
|
18
|
+
"@deepseek-ai/schemastery": "^3.18.5",
|
|
19
|
+
"@melite/comfyui-card-kit": "0.2.0-alpha",
|
|
20
|
+
"@melite/contracts": "0.2.0-alpha",
|
|
21
|
+
"@melite/models-seedvr2-ema": "0.2.0-alpha"
|
|
19
22
|
},
|
|
20
23
|
"devDependencies": {
|
|
21
24
|
"@types/node": "^22.20.0",
|
|
22
25
|
"typescript": "^5.9.3",
|
|
23
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
26
|
+
"@deepseek-ai/cordis": "^4.0.5"
|
|
24
27
|
},
|
|
25
28
|
"name": "@melite/image-upscale-tools",
|
|
26
29
|
"files": [
|
|
@@ -29,7 +32,7 @@
|
|
|
29
32
|
"lib/**/*.d.ts"
|
|
30
33
|
],
|
|
31
34
|
"peerDependencies": {
|
|
32
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
35
|
+
"@deepseek-ai/cordis": "^4.0.5"
|
|
33
36
|
},
|
|
34
37
|
"scripts": {
|
|
35
38
|
"build": "tsc -p tsconfig.build.json",
|