comfyui-node 1.2.0 → 1.3.1

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 CHANGED
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
package/README.md CHANGED
@@ -25,6 +25,8 @@ TypeScript SDK for interacting with the [ComfyUI](https://github.com/comfyanonym
25
25
  - [Modular Features (`api.ext`)](#modular-features-apiext)
26
26
  - [Events](#events)
27
27
  - [Preview Metadata](#preview-metadata)
28
+ - [API Nodes (Comfy.org paid)](#api-nodes-comfyorg-paid)
29
+ - [Image Inputs: Attach Files (DX)](#image-inputs-attach-files-dx)
28
30
  - [1.0 Migration](#10-migration)
29
31
  - [Reference Overview](#reference-overview)
30
32
  - [Examples](#examples)
@@ -65,7 +67,7 @@ npm install comfyui-node
65
67
  pnpm add comfyui-node
66
68
  # or
67
69
  bun add comfyui-node
68
- ```ts
70
+ ```
69
71
 
70
72
  TypeScript types are bundled; no extra install needed.
71
73
 
@@ -87,7 +89,7 @@ async function main() {
87
89
  }
88
90
  }
89
91
  main();
90
- ```ts
92
+ ```
91
93
 
92
94
  ## Cheat Sheet
93
95
 
@@ -613,8 +615,6 @@ Auto‑generated metadata keys:
613
615
 
614
616
  ---
615
617
 
616
- ```
617
-
618
618
  ### Job Weighting
619
619
 
620
620
  Jobs are inserted into an internal priority queue ordered by ascending weight. Lower weight runs earlier. By default the weight is set to the queue length at insertion (FIFO). You can override:
@@ -878,6 +878,128 @@ Troubleshooting:
878
878
 
879
879
  ---
880
880
 
881
+ ## API Nodes (Comfy.org paid)
882
+
883
+ Some workflows use paid API nodes (for example, Luma/Photon) that communicate progress and results via additional binary WebSocket frames. This SDK supports those nodes by:
884
+
885
+ - Allowing you to pass your Comfy.org API key to the server with each job
886
+ - Emitting low-level events for binary/text frames so you can surface progress and result URLs
887
+
888
+ ### Enabling API-node runs
889
+
890
+ Provide your key through the `comfyOrgApiKey` client option (recommended to source it from an environment variable):
891
+
892
+ ```ts
893
+ import { ComfyApi, Workflow } from 'comfyui-node';
894
+ import LumaPhoton from './your-luma-photon-workflow.json';
895
+
896
+ const api = await new ComfyApi(
897
+ process.env.COMFY_HOST || 'http://127.0.0.1:8188',
898
+ undefined,
899
+ {
900
+ comfyOrgApiKey: process.env.COMFY_ORG_API_KEY,
901
+ wsTimeout: 30000, // API nodes may take longer; increase if needed
902
+ debug: true // optional: structured socket + polling logs
903
+ }
904
+ ).ready();
905
+
906
+ // Minimal example: set prompt/seed, declare output, observe events
907
+ const wf = Workflow.fromAugmented(LumaPhoton)
908
+ .input('LUMA', 'prompt', 'Old photograph of the Guanabara Bay in Rio de Janeiro, aerial view')
909
+ .input('LUMA', 'seed', -1) // -1 => randomized; see _autoSeeds in result
910
+ .output('final_images', '2'); // alias, nodeId (auto-corrects if swapped)
911
+
912
+ // Low-level API-node events (binary channel text + raw preview bytes)
913
+ api.on('b_text', (ev) => {
914
+ const text = (ev as any).detail as string;
915
+ if (typeof text === 'string') console.log('[api-node text]', text.slice(0, 200));
916
+ });
917
+ api.on('b_text_meta', (ev) => {
918
+ // { channel: number, text: string }
919
+ console.log('[api-node text meta]', (ev as any).detail);
920
+ });
921
+ api.on('b_preview_raw', (ev) => {
922
+ const bytes = (ev as any).detail as Uint8Array;
923
+ console.log('[api-node preview raw bytes]', bytes?.byteLength);
924
+ });
925
+
926
+ const job = await api.run(wf, { autoDestroy: true });
927
+
928
+ job
929
+ .on('start', (id) => console.log('[start]', id))
930
+ .on('progress_pct', (p) => process.stdout.write(`\rprogress ${p}% `))
931
+ .on('preview', (blob) => console.log('\npreview bytes=', blob.size))
932
+ .on('failed', (e) => console.error('\nfailed', e));
933
+
934
+ const result = await job.done();
935
+ console.log('\nPrompt ID:', result._promptId);
936
+ for (const img of (result.final_images?.images || [])) {
937
+ console.log('image path:', api.ext.file.getPathImage(img));
938
+ }
939
+ ```
940
+
941
+ Notes:
942
+
943
+ - API-node text frames often include human-readable progress and a final “Result URL:” line. The SDK exposes the raw text via `b_text` and `{ channel, text }` via `b_text_meta` so you can parse or display them as desired.
944
+ - For long-running API calls, increase `wsTimeout` and consider enabling `debug` or setting `COMFY_DEBUG=1` to troubleshoot reconnection/polling.
945
+ - Output declaration accepts any of: `'alias:NodeId'`, `('alias','NodeId')`, or `'NodeId'`. If you accidentally swap the alias/id parameters, the SDK will auto-correct and warn.
946
+
947
+ Security tip: Never print your API key. The built-in debug logger redacts common key/authorization fields automatically.
948
+
949
+ ---
950
+
951
+ ## Image Inputs: Attach Files (DX)
952
+
953
+ When a workflow references images (e.g., `LoadImage.image = "IMAGE_A.png"` or folder loaders such as `LoadImageSetFromFolderNode`), you can attach local buffers directly to the `Workflow` and let the SDK handle uploads before execution.
954
+
955
+ Helpers:
956
+
957
+ - `wf.attachImage(nodeId, inputName, data, fileName, opts?)`
958
+ - Uploads `data` (Blob/Buffer/ArrayBuffer/Uint8Array) and sets the node input to `fileName` automatically.
959
+ - Options: `{ subfolder?: string; override?: boolean }`.
960
+ - `wf.attachFolderFiles(subfolder, files[], opts?)`
961
+ - Upload multiple files into a server subfolder; ideal for folder‑based loaders.
962
+
963
+ Example (see `scripts/image-loading-demo.ts`):
964
+
965
+ ```ts
966
+ import { ComfyApi, Workflow } from 'comfyui-node';
967
+ import Graph from './ImageLoading.json';
968
+ import * as fs from 'node:fs/promises';
969
+ import * as path from 'node:path';
970
+
971
+ const api = await new ComfyApi(process.env.COMFY_HOST || 'http://127.0.0.1:8188').ready();
972
+ const wf = Workflow.from(Graph);
973
+
974
+ // Attach two individual images for LoadImage nodes 2 and 4
975
+ const dir = path.resolve(process.cwd(), 'scripts', 'example_images');
976
+ const a = await fs.readFile(path.join(dir, 'IMAGE_A.png'));
977
+ const b = await fs.readFile(path.join(dir, 'IMAGE_B.png'));
978
+ wf.attachImage('2', 'image', a, 'IMAGE_A.png', { override: true })
979
+ .attachImage('4', 'image', b, 'IMAGE_B.png', { override: true });
980
+
981
+ // Attach an entire folder for node 5 (LoadImageSetFromFolderNode)
982
+ const files = (await fs.readdir(dir))
983
+ .filter(f => /\.(png|jpe?g|webp)$/i.test(f))
984
+ .map(async f => ({ fileName: f, data: await fs.readFile(path.join(dir, f)) }));
985
+ wf.attachFolderFiles('EXAMPLE_IMAGES', await Promise.all(files), { override: true });
986
+ wf.set('5.inputs.folder', 'EXAMPLE_IMAGES');
987
+
988
+ // Collect a simple output target for demonstration
989
+ wf.output('1');
990
+
991
+ const job = await api.run(wf, { autoDestroy: true });
992
+ job.on('progress_pct', p => process.stdout.write(`\rprogress ${p}% `));
993
+ await job.done();
994
+ ```
995
+
996
+ Notes:
997
+
998
+ - The inputs are updated to point at the uploaded filenames; subfolders are handled server‑side.
999
+ - Use `override: true` to replace existing files with the same name if needed.
1000
+
1001
+ ---
1002
+
881
1003
  ## 1.0 Migration
882
1004
 
883
1005
  All legacy `ComfyApi` instance methods listed below were **removed in 1.0.0** after a deprecation window in 0.2.x. Migrate to the `api.ext.*` namespaces. If you're upgrading from <1.0, replace calls as shown. No runtime warnings remain (they were stripped with the removals).