@tscomfy/core 0.0.0-stage → 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 (258) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -2
  3. package/dist/api/export.d.ts +49 -0
  4. package/dist/api/export.d.ts.map +1 -0
  5. package/dist/api/export.js +318 -0
  6. package/dist/api/export.js.map +1 -0
  7. package/dist/api/import.d.ts +40 -0
  8. package/dist/api/import.d.ts.map +1 -0
  9. package/dist/api/import.js +256 -0
  10. package/dist/api/import.js.map +1 -0
  11. package/dist/api/modes.d.ts +17 -0
  12. package/dist/api/modes.d.ts.map +1 -0
  13. package/dist/api/modes.js +264 -0
  14. package/dist/api/modes.js.map +1 -0
  15. package/dist/api/prompt.d.ts +21 -0
  16. package/dist/api/prompt.d.ts.map +1 -0
  17. package/dist/api/prompt.js +9 -0
  18. package/dist/api/prompt.js.map +1 -0
  19. package/dist/api/wire.d.ts +7 -0
  20. package/dist/api/wire.d.ts.map +1 -0
  21. package/dist/api/wire.js +11 -0
  22. package/dist/api/wire.js.map +1 -0
  23. package/dist/diagnostic/diagnostic.d.ts +83 -0
  24. package/dist/diagnostic/diagnostic.d.ts.map +1 -0
  25. package/dist/diagnostic/diagnostic.js +69 -0
  26. package/dist/diagnostic/diagnostic.js.map +1 -0
  27. package/dist/diagnostic/validation-error.d.ts +10 -0
  28. package/dist/diagnostic/validation-error.d.ts.map +1 -0
  29. package/dist/diagnostic/validation-error.js +17 -0
  30. package/dist/diagnostic/validation-error.js.map +1 -0
  31. package/dist/frontend/links.d.ts +21 -0
  32. package/dist/frontend/links.d.ts.map +1 -0
  33. package/dist/frontend/links.js +57 -0
  34. package/dist/frontend/links.js.map +1 -0
  35. package/dist/frontend/node.d.ts +112 -0
  36. package/dist/frontend/node.d.ts.map +1 -0
  37. package/dist/frontend/node.js +547 -0
  38. package/dist/frontend/node.js.map +1 -0
  39. package/dist/frontend/text.d.ts +34 -0
  40. package/dist/frontend/text.d.ts.map +1 -0
  41. package/dist/frontend/text.js +63 -0
  42. package/dist/frontend/text.js.map +1 -0
  43. package/dist/frontend/widgets.d.ts +35 -0
  44. package/dist/frontend/widgets.d.ts.map +1 -0
  45. package/dist/frontend/widgets.js +112 -0
  46. package/dist/frontend/widgets.js.map +1 -0
  47. package/dist/graph/graph.d.ts +57 -0
  48. package/dist/graph/graph.d.ts.map +1 -0
  49. package/dist/graph/graph.js +2 -0
  50. package/dist/graph/graph.js.map +1 -0
  51. package/dist/graph/operations.d.ts +15 -0
  52. package/dist/graph/operations.d.ts.map +1 -0
  53. package/dist/graph/operations.js +103 -0
  54. package/dist/graph/operations.js.map +1 -0
  55. package/dist/graph/output-ref.d.ts +11 -0
  56. package/dist/graph/output-ref.d.ts.map +1 -0
  57. package/dist/graph/output-ref.js +34 -0
  58. package/dist/graph/output-ref.js.map +1 -0
  59. package/dist/graph/types.d.ts +57 -0
  60. package/dist/graph/types.d.ts.map +1 -0
  61. package/dist/graph/types.js +4 -0
  62. package/dist/graph/types.js.map +1 -0
  63. package/dist/graph/workflow.d.ts +31 -0
  64. package/dist/graph/workflow.d.ts.map +1 -0
  65. package/dist/graph/workflow.js +277 -0
  66. package/dist/graph/workflow.js.map +1 -0
  67. package/dist/hash/sha256.d.ts +8 -0
  68. package/dist/hash/sha256.d.ts.map +1 -0
  69. package/dist/hash/sha256.js +116 -0
  70. package/dist/hash/sha256.js.map +1 -0
  71. package/dist/index.d.ts +31 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +26 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/json/parse.d.ts +28 -0
  76. package/dist/json/parse.d.ts.map +1 -0
  77. package/dist/json/parse.js +145 -0
  78. package/dist/json/parse.js.map +1 -0
  79. package/dist/json/stringify.d.ts +16 -0
  80. package/dist/json/stringify.d.ts.map +1 -0
  81. package/dist/json/stringify.js +32 -0
  82. package/dist/json/stringify.js.map +1 -0
  83. package/dist/json/value.d.ts +16 -0
  84. package/dist/json/value.d.ts.map +1 -0
  85. package/dist/json/value.js +9 -0
  86. package/dist/json/value.js.map +1 -0
  87. package/dist/object-info/context.d.ts +29 -0
  88. package/dist/object-info/context.d.ts.map +1 -0
  89. package/dist/object-info/context.js +51 -0
  90. package/dist/object-info/context.js.map +1 -0
  91. package/dist/object-info/frontend-widgets.d.ts +18 -0
  92. package/dist/object-info/frontend-widgets.d.ts.map +1 -0
  93. package/dist/object-info/frontend-widgets.js +34 -0
  94. package/dist/object-info/frontend-widgets.js.map +1 -0
  95. package/dist/object-info/inputs.d.ts +10 -0
  96. package/dist/object-info/inputs.d.ts.map +1 -0
  97. package/dist/object-info/inputs.js +140 -0
  98. package/dist/object-info/inputs.js.map +1 -0
  99. package/dist/object-info/normalize.d.ts +26 -0
  100. package/dist/object-info/normalize.d.ts.map +1 -0
  101. package/dist/object-info/normalize.js +91 -0
  102. package/dist/object-info/normalize.js.map +1 -0
  103. package/dist/object-info/numbers.d.ts +31 -0
  104. package/dist/object-info/numbers.d.ts.map +1 -0
  105. package/dist/object-info/numbers.js +91 -0
  106. package/dist/object-info/numbers.js.map +1 -0
  107. package/dist/object-info/outputs.d.ts +11 -0
  108. package/dist/object-info/outputs.d.ts.map +1 -0
  109. package/dist/object-info/outputs.js +96 -0
  110. package/dist/object-info/outputs.js.map +1 -0
  111. package/dist/object-info/socket-type.d.ts +9 -0
  112. package/dist/object-info/socket-type.d.ts.map +1 -0
  113. package/dist/object-info/socket-type.js +21 -0
  114. package/dist/object-info/socket-type.js.map +1 -0
  115. package/dist/object-info/spec-reader.d.ts +48 -0
  116. package/dist/object-info/spec-reader.d.ts.map +1 -0
  117. package/dist/object-info/spec-reader.js +474 -0
  118. package/dist/object-info/spec-reader.js.map +1 -0
  119. package/dist/schema/accepts.d.ts +26 -0
  120. package/dist/schema/accepts.d.ts.map +1 -0
  121. package/dist/schema/accepts.js +88 -0
  122. package/dist/schema/accepts.js.map +1 -0
  123. package/dist/schema/combo.d.ts +5 -0
  124. package/dist/schema/combo.d.ts.map +1 -0
  125. package/dist/schema/combo.js +7 -0
  126. package/dist/schema/combo.js.map +1 -0
  127. package/dist/schema/diff.d.ts +45 -0
  128. package/dist/schema/diff.d.ts.map +1 -0
  129. package/dist/schema/diff.js +69 -0
  130. package/dist/schema/diff.js.map +1 -0
  131. package/dist/schema/freeze.d.ts +9 -0
  132. package/dist/schema/freeze.d.ts.map +1 -0
  133. package/dist/schema/freeze.js +20 -0
  134. package/dist/schema/freeze.js.map +1 -0
  135. package/dist/schema/frontend.d.ts +11 -0
  136. package/dist/schema/frontend.d.ts.map +1 -0
  137. package/dist/schema/frontend.js +75 -0
  138. package/dist/schema/frontend.js.map +1 -0
  139. package/dist/schema/hash.d.ts +9 -0
  140. package/dist/schema/hash.d.ts.map +1 -0
  141. package/dist/schema/hash.js +13 -0
  142. package/dist/schema/hash.js.map +1 -0
  143. package/dist/schema/lookup.d.ts +7 -0
  144. package/dist/schema/lookup.d.ts.map +1 -0
  145. package/dist/schema/lookup.js +8 -0
  146. package/dist/schema/lookup.js.map +1 -0
  147. package/dist/schema/type-text.d.ts +6 -0
  148. package/dist/schema/type-text.d.ts.map +1 -0
  149. package/dist/schema/type-text.js +16 -0
  150. package/dist/schema/type-text.js.map +1 -0
  151. package/dist/schema/typed.d.ts +34 -0
  152. package/dist/schema/typed.d.ts.map +1 -0
  153. package/dist/schema/typed.js +52 -0
  154. package/dist/schema/typed.js.map +1 -0
  155. package/dist/schema/types.d.ts +261 -0
  156. package/dist/schema/types.d.ts.map +1 -0
  157. package/dist/schema/types.js +2 -0
  158. package/dist/schema/types.js.map +1 -0
  159. package/dist/ui/export.d.ts +44 -0
  160. package/dist/ui/export.d.ts.map +1 -0
  161. package/dist/ui/export.js +399 -0
  162. package/dist/ui/export.js.map +1 -0
  163. package/dist/ui/format.d.ts +15 -0
  164. package/dist/ui/format.d.ts.map +1 -0
  165. package/dist/ui/format.js +23 -0
  166. package/dist/ui/format.js.map +1 -0
  167. package/dist/ui/import/emit.d.ts +26 -0
  168. package/dist/ui/import/emit.d.ts.map +1 -0
  169. package/dist/ui/import/emit.js +183 -0
  170. package/dist/ui/import/emit.js.map +1 -0
  171. package/dist/ui/import/file.d.ts +71 -0
  172. package/dist/ui/import/file.d.ts.map +1 -0
  173. package/dist/ui/import/file.js +309 -0
  174. package/dist/ui/import/file.js.map +1 -0
  175. package/dist/ui/import/graph.d.ts +62 -0
  176. package/dist/ui/import/graph.d.ts.map +1 -0
  177. package/dist/ui/import/graph.js +21 -0
  178. package/dist/ui/import/graph.js.map +1 -0
  179. package/dist/ui/import/placement.d.ts +37 -0
  180. package/dist/ui/import/placement.d.ts.map +1 -0
  181. package/dist/ui/import/placement.js +216 -0
  182. package/dist/ui/import/placement.js.map +1 -0
  183. package/dist/ui/import/primitives.d.ts +22 -0
  184. package/dist/ui/import/primitives.d.ts.map +1 -0
  185. package/dist/ui/import/primitives.js +194 -0
  186. package/dist/ui/import/primitives.js.map +1 -0
  187. package/dist/ui/import/report.d.ts +4 -0
  188. package/dist/ui/import/report.d.ts.map +1 -0
  189. package/dist/ui/import/report.js +2 -0
  190. package/dist/ui/import/report.js.map +1 -0
  191. package/dist/ui/import/resolve.d.ts +53 -0
  192. package/dist/ui/import/resolve.d.ts.map +1 -0
  193. package/dist/ui/import/resolve.js +244 -0
  194. package/dist/ui/import/resolve.js.map +1 -0
  195. package/dist/ui/import/widget-values.d.ts +31 -0
  196. package/dist/ui/import/widget-values.d.ts.map +1 -0
  197. package/dist/ui/import/widget-values.js +237 -0
  198. package/dist/ui/import/widget-values.js.map +1 -0
  199. package/dist/ui/import.d.ts +23 -0
  200. package/dist/ui/import.d.ts.map +1 -0
  201. package/dist/ui/import.js +132 -0
  202. package/dist/ui/import.js.map +1 -0
  203. package/dist/validate/validate-api.d.ts +16 -0
  204. package/dist/validate/validate-api.d.ts.map +1 -0
  205. package/dist/validate/validate-api.js +561 -0
  206. package/dist/validate/validate-api.js.map +1 -0
  207. package/package.json +43 -4
  208. package/src/api/export.ts +424 -0
  209. package/src/api/import.ts +310 -0
  210. package/src/api/modes.ts +308 -0
  211. package/src/api/prompt.ts +25 -0
  212. package/src/api/wire.ts +11 -0
  213. package/src/diagnostic/diagnostic.ts +98 -0
  214. package/src/diagnostic/validation-error.ts +24 -0
  215. package/src/frontend/links.ts +63 -0
  216. package/src/frontend/node.ts +658 -0
  217. package/src/frontend/text.ts +80 -0
  218. package/src/frontend/widgets.ts +135 -0
  219. package/src/graph/graph.ts +69 -0
  220. package/src/graph/operations.ts +116 -0
  221. package/src/graph/output-ref.ts +40 -0
  222. package/src/graph/types.ts +65 -0
  223. package/src/graph/workflow.ts +329 -0
  224. package/src/hash/sha256.ts +116 -0
  225. package/src/index.ts +89 -0
  226. package/src/json/parse.ts +187 -0
  227. package/src/json/stringify.ts +30 -0
  228. package/src/json/value.ts +25 -0
  229. package/src/object-info/context.ts +85 -0
  230. package/src/object-info/frontend-widgets.ts +38 -0
  231. package/src/object-info/inputs.ts +246 -0
  232. package/src/object-info/normalize.ts +158 -0
  233. package/src/object-info/numbers.ts +99 -0
  234. package/src/object-info/outputs.ts +146 -0
  235. package/src/object-info/socket-type.ts +22 -0
  236. package/src/object-info/spec-reader.ts +704 -0
  237. package/src/schema/accepts.ts +87 -0
  238. package/src/schema/combo.ts +11 -0
  239. package/src/schema/diff.ts +113 -0
  240. package/src/schema/freeze.ts +21 -0
  241. package/src/schema/frontend.ts +80 -0
  242. package/src/schema/hash.ts +14 -0
  243. package/src/schema/lookup.ts +9 -0
  244. package/src/schema/type-text.ts +18 -0
  245. package/src/schema/typed.ts +77 -0
  246. package/src/schema/types.ts +289 -0
  247. package/src/ui/export.ts +513 -0
  248. package/src/ui/format.ts +26 -0
  249. package/src/ui/import/emit.ts +224 -0
  250. package/src/ui/import/file.ts +426 -0
  251. package/src/ui/import/graph.ts +83 -0
  252. package/src/ui/import/placement.ts +232 -0
  253. package/src/ui/import/primitives.ts +209 -0
  254. package/src/ui/import/report.ts +8 -0
  255. package/src/ui/import/resolve.ts +332 -0
  256. package/src/ui/import/widget-values.ts +292 -0
  257. package/src/ui/import.ts +161 -0
  258. package/src/validate/validate-api.ts +710 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 the tscomfy authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,39 @@
1
- # Temporary Holding Version
1
+ # @tscomfy/core
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Type-safe ComfyUI workflows in TypeScript: the `/object_info` normalizer and schema model, the
4
+ workflow builder, API and UI format export and import, validation and graph operations. No
5
+ runtime dependencies; runs in Node, Bun, Deno and browsers.
6
+
7
+ ```sh
8
+ npm install @tscomfy/core
9
+ npm install --save-dev @tscomfy/cli
10
+ npx tscomfy generate --url http://127.0.0.1:8188 --out src/comfy/local
11
+ ```
12
+
13
+ ```ts
14
+ import { stringify, toApi, workflow } from "@tscomfy/core";
15
+ import { local } from "./comfy/local/index.js"; // generated from your server
16
+
17
+ const txt2img = workflow(local, ({ n }) => {
18
+ const [model, clip, vae] = n.CheckpointLoaderSimple({ ckpt_name: "sd_xl_base_1.0.safetensors" });
19
+ const latent = n.KSampler({
20
+ model,
21
+ positive: n.CLIPTextEncode({ clip, text: "a cat in a hat" }),
22
+ negative: n.CLIPTextEncode({ clip, text: "" }),
23
+ latent_image: n.EmptyLatentImage({ width: 1024, height: 1024 }),
24
+ seed: 42n,
25
+ sampler_name: "euler",
26
+ scheduler: "normal",
27
+ });
28
+ n.SaveImage({ images: n.VAEDecode({ samples: latent, vae }) });
29
+ });
30
+
31
+ const body = stringify({ prompt: toApi(txt2img) }); // POST it to /prompt
32
+ ```
33
+
34
+ Needs ES2024 and `JSON.parse` source-text access (Node 24 or later, Bun 1.4 or later).
35
+ See the [guides](https://github.com/TheeKia/tscomfy/tree/main/docs/guides), starting with [getting started](https://github.com/TheeKia/tscomfy/tree/main/docs/guides/getting-started.md).
36
+
37
+ ## License
38
+
39
+ MIT
@@ -0,0 +1,49 @@
1
+ import { type Diagnostic } from "../diagnostic/diagnostic.ts";
2
+ import type { Workflow } from "../graph/graph.ts";
3
+ import type { ApiPrompt } from "./prompt.ts";
4
+ /** Options for {@link toApi} and {@link exportApi}. */
5
+ export interface ToApiOptions {
6
+ /** Emit `_meta.title`, as the frontend does. Default `true`. */
7
+ readonly meta?: boolean;
8
+ /**
9
+ * Validate the prompt against the schema, as {@link validateApi} does. Default `true`.
10
+ * Problems building the prompt itself are reported either way.
11
+ */
12
+ readonly validate?: boolean;
13
+ /**
14
+ * Apply bypass and mute. Default `true`. With `false`, every node is sent
15
+ * as if it ran, as a tool that rewrites workflows needs (the transpiler).
16
+ */
17
+ readonly modes?: boolean;
18
+ }
19
+ /** What {@link exportApi} returns. */
20
+ export interface ApiExportResult {
21
+ /** The prompt, built even when there are errors: whatever could be sent. */
22
+ readonly prompt: ApiPrompt;
23
+ /** Problems building the prompt, then, unless `validate` is `false`, validating it. */
24
+ readonly diagnostics: readonly Diagnostic[];
25
+ }
26
+ /**
27
+ * Converts a workflow into an API-format prompt: explicit schema
28
+ * defaults filled in, dynamic inputs flattened to their wire keys, list values wrapped, keys in
29
+ * the frontend's order. Serialize it with `stringify`, which keeps big integers exact.
30
+ *
31
+ * Throws a {@link ValidationError}, carrying every diagnostic, when there is an error: the
32
+ * prompt can't be built faithfully (`E_INPUT_KEY_COLLISION`, `E_TOO_MANY_DYNAMIC_INPUTS`), or,
33
+ * unless `validate` is `false`, the backend would reject it. Warnings don't throw; use
34
+ * {@link exportApi} to see them. Throws a `TypeError` for an output reference nested inside a
35
+ * JSON value, which no input can carry.
36
+ */
37
+ export declare function toApi(workflow: Workflow, options?: ToApiOptions): ApiPrompt;
38
+ /**
39
+ * {@link toApi} without throwing: the prompt, and what went wrong building and validating it.
40
+ */
41
+ export declare function exportApi(workflow: Workflow, options?: ToApiOptions): ApiExportResult;
42
+ /**
43
+ * Every problem with a workflow: the errors {@link toApi} would throw for, and
44
+ * the warnings, which don't stop the backend (a value outside an upload combo's listed files, for
45
+ * example). Empty for a workflow the backend accepts with nothing to report. Throws a `TypeError`
46
+ * where {@link toApi} does.
47
+ */
48
+ export declare function validate(workflow: Workflow): readonly Diagnostic[];
49
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/api/export.ts"],"names":[],"mappings":"AAUA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGhF,OAAO,KAAK,EAAyB,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAOzE,OAAO,KAAK,EAAW,SAAS,EAAE,MAAM,aAAa,CAAC;AAEtD,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,uFAAuF;IACvF,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAC;CAC7C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,GAAE,YAAiB,GAAG,SAAS,CAM/E;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,GAAE,YAAiB,GAAG,eAAe,CA6BzF;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,UAAU,EAAE,CAElE"}
@@ -0,0 +1,318 @@
1
+ // Graph → API-format prompt (docs/plan.md §7.4), byte for byte what the ComfyUI frontend sends
2
+ // for the same graph. The frontend's rules (ComfyUI_frontend 1.55.17 `executionUtil.ts`
3
+ // `graphToPrompt`, `litegraphService.ts`, `dynamicWidgets.ts`):
4
+ // - every widget value is sent, in widget order; a linked widget keeps its widget's position;
5
+ // - then every connected socket that isn't a widget, in input order;
6
+ // - a dynamic combo's option widgets follow it depth-first; its option sockets come after the
7
+ // node's own sockets;
8
+ // - arrays are wrapped as `{"__value__": [...]}`, CURVE values as `{"__type__": "CURVE", …}`;
9
+ // - `_meta.title` is always present.
10
+ import { createDiagnostic } from "../diagnostic/diagnostic.js";
11
+ import { ValidationError } from "../diagnostic/validation-error.js";
12
+ import { sendsInputValue } from "../frontend/widgets.js";
13
+ import { isOutputRef } from "../graph/output-ref.js";
14
+ import { validateApi } from "../validate/validate-api.js";
15
+ import { applyModes } from "./modes.js";
16
+ /**
17
+ * Converts a workflow into an API-format prompt: explicit schema
18
+ * defaults filled in, dynamic inputs flattened to their wire keys, list values wrapped, keys in
19
+ * the frontend's order. Serialize it with `stringify`, which keeps big integers exact.
20
+ *
21
+ * Throws a {@link ValidationError}, carrying every diagnostic, when there is an error: the
22
+ * prompt can't be built faithfully (`E_INPUT_KEY_COLLISION`, `E_TOO_MANY_DYNAMIC_INPUTS`), or,
23
+ * unless `validate` is `false`, the backend would reject it. Warnings don't throw; use
24
+ * {@link exportApi} to see them. Throws a `TypeError` for an output reference nested inside a
25
+ * JSON value, which no input can carry.
26
+ */
27
+ export function toApi(workflow, options = {}) {
28
+ const { prompt, diagnostics } = exportApi(workflow, options);
29
+ if (diagnostics.some((diagnostic) => diagnostic.severity === "error")) {
30
+ throw new ValidationError(diagnostics);
31
+ }
32
+ return prompt;
33
+ }
34
+ /**
35
+ * {@link toApi} without throwing: the prompt, and what went wrong building and validating it.
36
+ */
37
+ export function exportApi(workflow, options = {}) {
38
+ const diagnostics = [];
39
+ const entries = [];
40
+ const modal = [];
41
+ for (const node of workflow.graph.nodes.values()) {
42
+ const definition = Object.hasOwn(workflow.schema.nodes, node.classType)
43
+ ? workflow.schema.nodes[node.classType]
44
+ : undefined;
45
+ const inputs = node.raw || definition === undefined
46
+ ? rawInputs(node)
47
+ : new NodeExport(node, definition, diagnostics).inputs();
48
+ const title = node.title ?? definition?.displayName ?? node.classType;
49
+ const exported = {
50
+ inputs,
51
+ class_type: node.classType,
52
+ ...(options.meta === false ? {} : { _meta: { title } }),
53
+ };
54
+ entries.push([node.id, exported]);
55
+ modal.push({ id: node.id, node: exported, definition, mode: node.mode });
56
+ }
57
+ // Bypassed and muted nodes aren't sent; links through them are resolved as the frontend does.
58
+ const prompt = Object.fromEntries(options.modes !== false && modal.some((node) => node.mode !== undefined)
59
+ ? applyModes(modal, diagnostics)
60
+ : entries);
61
+ if (options.validate !== false)
62
+ diagnostics.push(...validateApi(prompt, workflow.schema));
63
+ return { prompt, diagnostics };
64
+ }
65
+ /**
66
+ * Every problem with a workflow: the errors {@link toApi} would throw for, and
67
+ * the warnings, which don't stop the backend (a value outside an upload combo's listed files, for
68
+ * example). Empty for a workflow the backend accepts with nothing to report. Throws a `TypeError`
69
+ * where {@link toApi} does.
70
+ */
71
+ export function validate(workflow) {
72
+ return exportApi(workflow).diagnostics;
73
+ }
74
+ /** The inputs of one node, gathered in the frontend's three groups. */
75
+ class NodeExport {
76
+ #node;
77
+ #definition;
78
+ #diagnostics;
79
+ #widgets = [];
80
+ #sockets = [];
81
+ #optionSockets = [];
82
+ #keys = new Set();
83
+ constructor(node, definition, diagnostics) {
84
+ this.#node = node;
85
+ this.#definition = definition;
86
+ this.#diagnostics = diagnostics;
87
+ }
88
+ inputs() {
89
+ const given = this.#node.inputs;
90
+ const known = new Set();
91
+ for (const input of this.#definition.inputs) {
92
+ known.add(input.name);
93
+ this.#input(input, Object.hasOwn(given, input.name) ? given[input.name] : undefined, input.name, false);
94
+ }
95
+ // Inputs the schema doesn't know are passed through after the rest; validation flags them.
96
+ for (const [name, value] of Object.entries(given)) {
97
+ if (!known.has(name))
98
+ this.#add(isOutputRef(value) ? "socket" : "widget", name, encode(value), false);
99
+ }
100
+ return Object.fromEntries([...this.#widgets, ...this.#sockets, ...this.#optionSockets]);
101
+ }
102
+ /** Adds one input at `key`; `inOption` is true inside a dynamic-combo option. */
103
+ #input(input, value, key, inOption) {
104
+ switch (input.kind) {
105
+ case "socket":
106
+ case "matchType":
107
+ case "unknown":
108
+ if (value !== undefined) {
109
+ this.#add(isOutputRef(value) ? "socket" : "widget", key, encode(value), inOption);
110
+ }
111
+ return;
112
+ case "combo":
113
+ // No widget, so no default: sent only as given, among the sockets when it is a link.
114
+ if (input.forceInput === true) {
115
+ if (value !== undefined) {
116
+ this.#add(isOutputRef(value) ? "socket" : "widget", key, encode(value), inOption);
117
+ }
118
+ return;
119
+ }
120
+ if (!sendsInputValue(input)) {
121
+ if (value !== undefined)
122
+ this.#passThrough(key, value, inOption);
123
+ return;
124
+ }
125
+ this.#widget(input, value, key, inOption);
126
+ return;
127
+ case "int":
128
+ case "float":
129
+ case "string":
130
+ case "boolean":
131
+ // An optional input whose widget the frontend never sends (CameraAngle's `view`) gets no
132
+ // default; a value given for it passes through.
133
+ if (!sendsInputValue(input)) {
134
+ if (value !== undefined)
135
+ this.#passThrough(key, value, inOption);
136
+ return;
137
+ }
138
+ this.#widget(input, value, key, inOption);
139
+ return;
140
+ case "value": {
141
+ // A display-only widget sends nothing; a value given for one passes through, and
142
+ // validation reports it.
143
+ if (!sendsInputValue(input)) {
144
+ if (value !== undefined)
145
+ this.#passThrough(key, value, inOption);
146
+ return;
147
+ }
148
+ const sent = value === undefined ? input.default : value;
149
+ if (sent === undefined)
150
+ return;
151
+ const encoded = encode(sent);
152
+ // The frontend marks CURVE values with their type; other objects pass as they are.
153
+ this.#add("widget", key, input.widget === "CURVE" && sent !== null && !isOutputRef(sent)
154
+ ? { __type__: "CURVE", __value__: encodedValue(sent) }
155
+ : encoded, inOption);
156
+ return;
157
+ }
158
+ case "dynamicCombo":
159
+ this.#dynamicCombo(input, value, key, inOption);
160
+ return;
161
+ case "autogrow":
162
+ this.#autogrow(input, value, key, inOption);
163
+ return;
164
+ case "dynamicGroup":
165
+ this.#dynamicGroup(input, value, key, inOption);
166
+ return;
167
+ }
168
+ }
169
+ /** A primitive widget: its value, or its default (the frontend's, §7.2) when none is given. */
170
+ #widget(input, value, key, inOption) {
171
+ // `null` is a value; only a missing input takes the default.
172
+ const sent = value === undefined ? input.default : value;
173
+ if (sent !== undefined)
174
+ this.#add("widget", key, encode(sent), inOption);
175
+ }
176
+ #dynamicCombo(input, value, key, inOption) {
177
+ if (value === undefined)
178
+ return;
179
+ if (isOutputRef(value)) {
180
+ this.#add("widget", key, encode(value), inOption);
181
+ return;
182
+ }
183
+ // A bare key, or `{ option, inputs? }`. Anything else passes through for validation.
184
+ const chosen = typeof value === "string" ? value : optionOf(value);
185
+ if (chosen === undefined) {
186
+ this.#add("widget", key, encode(value), inOption);
187
+ return;
188
+ }
189
+ const children = isRecord(value) && isRecord(value["inputs"]) ? value["inputs"] : {};
190
+ this.#add("widget", key, chosen, inOption);
191
+ const option = input.options.find((each) => each.key === chosen);
192
+ const known = new Set();
193
+ for (const child of option?.inputs ?? []) {
194
+ known.add(child.name);
195
+ this.#input(child, Object.hasOwn(children, child.name) ? children[child.name] : undefined, `${key}.${child.name}`, true);
196
+ }
197
+ this.#unknown(children, known, `${key}.`, true);
198
+ }
199
+ #autogrow(input, value, key, inOption) {
200
+ if (value === undefined)
201
+ return;
202
+ // Only given (connected) slots are sent, in slot order.
203
+ if (isList(value)) {
204
+ if (value.length > input.slots.length)
205
+ this.#tooMany(key, value.length, input.slots.length);
206
+ input.slots.slice(0, value.length).forEach((slot, index) => {
207
+ this.#input(input.template, value[index], `${key}.${slot}`, inOption);
208
+ });
209
+ }
210
+ else if (isRecord(value)) {
211
+ for (const slot of input.slots) {
212
+ if (Object.hasOwn(value, slot)) {
213
+ this.#input(input.template, value[slot], `${key}.${slot}`, inOption);
214
+ }
215
+ }
216
+ this.#unknown(value, new Set(input.slots), `${key}.`, inOption);
217
+ }
218
+ else {
219
+ this.#passThrough(key, value, inOption);
220
+ }
221
+ }
222
+ #dynamicGroup(input, value, key, inOption) {
223
+ if (value === undefined)
224
+ return;
225
+ if (!isList(value)) {
226
+ this.#passThrough(key, value, inOption);
227
+ return;
228
+ }
229
+ if (value.length > input.max)
230
+ this.#tooMany(key, value.length, input.max);
231
+ const names = new Set(input.fields.map((field) => field.name));
232
+ value.slice(0, input.max).forEach((row, index) => {
233
+ const prefix = `${key}.${String(index)}`;
234
+ if (!isRecord(row)) {
235
+ this.#passThrough(prefix, row, inOption);
236
+ return;
237
+ }
238
+ const fields = row;
239
+ for (const field of input.fields) {
240
+ this.#input(field, Object.hasOwn(fields, field.name) ? fields[field.name] : undefined, `${prefix}.${field.name}`, inOption);
241
+ }
242
+ this.#unknown(fields, names, `${prefix}.`, inOption);
243
+ });
244
+ }
245
+ /**
246
+ * Keys inside a structured value that the schema doesn't know: passed through after the known
247
+ * ones, as unknown top-level inputs are; validation flags them.
248
+ */
249
+ #unknown(values, known, prefix, inOption) {
250
+ for (const [name, value] of Object.entries(values)) {
251
+ if (!known.has(name)) {
252
+ this.#add(isOutputRef(value) ? "socket" : "widget", `${prefix}${name}`, encode(value), inOption);
253
+ }
254
+ }
255
+ }
256
+ /** A value whose shape its input can't take: sent under `key` as given, for validation. */
257
+ #passThrough(key, value, inOption) {
258
+ this.#add(isOutputRef(value) ? "socket" : "widget", key, encode(value), inOption);
259
+ }
260
+ /** More slots or rows than the backend reads: the rest can't be sent. */
261
+ #tooMany(key, given, most) {
262
+ this.#diagnostics.push(createDiagnostic("E_TOO_MANY_DYNAMIC_INPUTS", [this.#node.id, "inputs", key], `Input ${key} of node ${this.#node.id} has ${String(given)} entries, but at most ${String(most)} can be sent; dropping the rest.`));
263
+ }
264
+ /** Places a key in its group; a key already taken is a collision. */
265
+ #add(group, key, value, inOption) {
266
+ if (this.#keys.has(key)) {
267
+ this.#diagnostics.push(createDiagnostic("E_INPUT_KEY_COLLISION", [this.#node.id, "inputs", key], `Two inputs of node ${this.#node.id} (${this.#node.classType}) both send the key ${JSON.stringify(key)}; keeping the first.`));
268
+ return;
269
+ }
270
+ this.#keys.add(key);
271
+ const target = group === "widget" ? this.#widgets : inOption ? this.#optionSockets : this.#sockets;
272
+ target.push([key, value]);
273
+ }
274
+ }
275
+ /** Inputs of a raw node, or of a class the schema doesn't know: passed through as given. */
276
+ function rawInputs(node) {
277
+ return Object.fromEntries(Object.entries(node.inputs).map(([key, value]) => [key, encode(value)]));
278
+ }
279
+ /**
280
+ * A value as the prompt carries it: a link as `[id, slot]`; a list wrapped in
281
+ * `{"__value__": [...]}`, because the backend reads a bare list as a link.
282
+ */
283
+ function encode(value) {
284
+ if (isOutputRef(value))
285
+ return [value.node, value.slot];
286
+ if (isList(value))
287
+ return { __value__: encodedValue(value) };
288
+ return encodedValue(value);
289
+ }
290
+ /** A plain JSON value; output references can only stand for a whole input. */
291
+ function encodedValue(value) {
292
+ if (isOutputRef(value)) {
293
+ throw new TypeError("toApi: an output reference can only be the whole value of an input");
294
+ }
295
+ if (isList(value))
296
+ return value.map(encodedValue);
297
+ if (isRecord(value)) {
298
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, encodedValue(item)]));
299
+ }
300
+ return value;
301
+ }
302
+ /** The option a `{ option, inputs? }` value chooses, or `undefined` for any other shape. */
303
+ function optionOf(value) {
304
+ if (!isRecord(value) || typeof value["option"] !== "string")
305
+ return undefined;
306
+ const keys = Object.keys(value);
307
+ const inputs = value["inputs"];
308
+ const shaped = keys.every((each) => each === "option" || each === "inputs") &&
309
+ (inputs === undefined || isRecord(inputs));
310
+ return shaped ? value["option"] : undefined;
311
+ }
312
+ function isList(value) {
313
+ return Array.isArray(value);
314
+ }
315
+ function isRecord(value) {
316
+ return (typeof value === "object" && value !== null && !Array.isArray(value) && !isOutputRef(value));
317
+ }
318
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/api/export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { type Diagnostic } from "../diagnostic/diagnostic.ts";
2
+ import type { Workflow } from "../graph/graph.ts";
3
+ import type { NodeId, NodeMode, Out } from "../graph/types.ts";
4
+ import { type AssembledNode } from "../graph/workflow.ts";
5
+ import { type JsonObject } from "../json/value.ts";
6
+ import type { TypedSchema } from "../schema/typed.ts";
7
+ /** What {@link importApi} returns. */
8
+ export interface ApiImportResult<N> {
9
+ /** The prompt as a workflow over `schema`; nodes it couldn't read are left out. */
10
+ readonly workflow: Workflow<N>;
11
+ /** Problems reading the prompt. Validation (`validate`) is separate. */
12
+ readonly diagnostics: readonly Diagnostic[];
13
+ }
14
+ /**
15
+ * Reads an API-format prompt (the JSON `POST /prompt` takes as `prompt`, or the frontend's
16
+ * "Export (API)") into a workflow over `schema`. Takes raw text, so big integers stay exact.
17
+ *
18
+ * Nodes keep their ids and titles. A node whose class the schema has gets structured inputs, as
19
+ * the builder records them; a node of an unknown class, or one whose keys don't fold back (a
20
+ * DynamicGroup with row gaps, keys under a dynamic combo's unknown option), is kept as a raw node
21
+ * with its wire keys, so it still exports as it came.
22
+ */
23
+ export declare function importApi<N>(text: string, schema: TypedSchema<N>): ApiImportResult<N>;
24
+ /** Makes an output reference of the workflow being built. */
25
+ export type Link = (node: NodeId, slot: number) => Out<string>;
26
+ /** A node as the wire carries it: class, wire keys (links as `[id, slot]`), title and mode. */
27
+ export interface WireNode {
28
+ readonly id: NodeId;
29
+ readonly classType: string;
30
+ readonly inputs: JsonObject;
31
+ /** The title shown, if any; one equal to the display name isn't kept. */
32
+ readonly title?: string;
33
+ readonly mode?: NodeMode;
34
+ }
35
+ /**
36
+ * A node of the wire, folded into structured inputs by the schema (the API and UI importers
37
+ * share it). Raw when the class is unknown or its keys don't fold back.
38
+ */
39
+ export declare function wireNode(node: WireNode, schema: TypedSchema<unknown>, link: Link, diagnostics: Diagnostic[]): AssembledNode;
40
+ //# sourceMappingURL=import.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/api/import.ts"],"names":[],"mappings":"AAIA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEhF,OAAO,KAAK,EAAc,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE5E,OAAO,EAA6B,KAAK,UAAU,EAAkB,MAAM,kBAAkB,CAAC;AAE9F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,sCAAsC;AACtC,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,mFAAmF;IACnF,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,WAAW,EAAE,SAAS,UAAU,EAAE,CAAC;CAC7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAoBrF;AAED,6DAA6D;AAC7D,MAAM,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC;AAgC/D,+FAA+F;AAC/F,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,EAC5B,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,UAAU,EAAE,GACxB,aAAa,CAyCf"}