diffusers-workflow 0.4.0__py3-none-any.whl

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 (260) hide show
  1. diffusers_workflow-0.4.0.dist-info/METADATA +318 -0
  2. diffusers_workflow-0.4.0.dist-info/RECORD +260 -0
  3. diffusers_workflow-0.4.0.dist-info/WHEEL +5 -0
  4. diffusers_workflow-0.4.0.dist-info/entry_points.txt +7 -0
  5. diffusers_workflow-0.4.0.dist-info/licenses/LICENSE +201 -0
  6. diffusers_workflow-0.4.0.dist-info/top_level.txt +2 -0
  7. dw/__init__.py +440 -0
  8. dw/adapter_compatibility.py +226 -0
  9. dw/arguments.py +1231 -0
  10. dw/assessment_rules.py +159 -0
  11. dw/assets.py +130 -0
  12. dw/cache_blocks.json +16 -0
  13. dw/cache_blocks.py +146 -0
  14. dw/community_pipelines/pipeline_flux_rf_inversion.py +1184 -0
  15. dw/content_types.py +150 -0
  16. dw/dissolve_frame_errors.py +121 -0
  17. dw/docs/ACCELERATION.md +352 -0
  18. dw/docs/AGENT_LOOP.md +95 -0
  19. dw/docs/DEPENDENCIES.md +91 -0
  20. dw/docs/IP_ADAPTER.md +109 -0
  21. dw/docs/LORAS.md +131 -0
  22. dw/docs/MCP.md +517 -0
  23. dw/docs/PROMPT_WEIGHTING.md +78 -0
  24. dw/docs/QUANTIZATION.md +230 -0
  25. dw/docs/RECIPES_24GB.md +201 -0
  26. dw/docs/RELEASING.md +195 -0
  27. dw/docs/REMOTE.md +140 -0
  28. dw/docs/REPL_COMMANDS.md +121 -0
  29. dw/docs/REPL_WORKER_GUIDE.md +51 -0
  30. dw/docs/SECURITY.md +272 -0
  31. dw/docs/SECURITY_QUICKREF.md +112 -0
  32. dw/docs/SERVER.md +679 -0
  33. dw/docs/TASKS.md +1741 -0
  34. dw/docs/TESTING.md +71 -0
  35. dw/docs/WORKFLOW_GUIDE.md +2038 -0
  36. dw/docs/WORKSPACES.md +316 -0
  37. dw/download_watch.py +335 -0
  38. dw/elision.py +306 -0
  39. dw/events.py +275 -0
  40. dw/for_each.py +409 -0
  41. dw/host_memory.py +258 -0
  42. dw/host_memory_projection.py +230 -0
  43. dw/hub_cache.py +432 -0
  44. dw/introspection.py +1228 -0
  45. dw/kernel_availability.py +208 -0
  46. dw/locations.py +599 -0
  47. dw/log_setup.py +45 -0
  48. dw/loudness.py +82 -0
  49. dw/media_audio.py +217 -0
  50. dw/media_frames.py +367 -0
  51. dw/media_info.py +297 -0
  52. dw/pipeline_processors/chain.py +821 -0
  53. dw/pipeline_processors/config_objects.py +237 -0
  54. dw/pipeline_processors/pipeline.py +2297 -0
  55. dw/pipeline_processors/remote.py +46 -0
  56. dw/plan.py +920 -0
  57. dw/previous_results.py +411 -0
  58. dw/probe_paths.py +59 -0
  59. dw/prompt_schema.json +48 -0
  60. dw/prompt_weighting.py +378 -0
  61. dw/prompts.py +159 -0
  62. dw/realize.py +250 -0
  63. dw/reference_limits.py +215 -0
  64. dw/reference_names.py +125 -0
  65. dw/repl.py +338 -0
  66. dw/repl_commands.py +836 -0
  67. dw/repl_worker.py +159 -0
  68. dw/result.py +1720 -0
  69. dw/result_fps.py +82 -0
  70. dw/run.py +162 -0
  71. dw/runs.py +768 -0
  72. dw/scalar_result_validation.py +97 -0
  73. dw/schema.py +283 -0
  74. dw/security.py +1038 -0
  75. dw/select_validation.py +115 -0
  76. dw/serve.py +277 -0
  77. dw/server/__init__.py +2 -0
  78. dw/server/app.py +4586 -0
  79. dw/server/assess.py +132 -0
  80. dw/server/catalog_shape.py +487 -0
  81. dw/server/enhancers.py +129 -0
  82. dw/server/exports.py +480 -0
  83. dw/server/guides.py +257 -0
  84. dw/server/jobs.py +1561 -0
  85. dw/server/mcp_mount.py +95 -0
  86. dw/server/netinfo.py +124 -0
  87. dw/server/observed_cost.py +379 -0
  88. dw/server/sysinfo.py +71 -0
  89. dw/server/ui/assets/abap-08VXUWAP.js +1 -0
  90. dw/server/ui/assets/apex-BWPQTe0t.js +1 -0
  91. dw/server/ui/assets/azcli-Bc_sGQ0U.js +1 -0
  92. dw/server/ui/assets/bat-i0X4ZdIN.js +1 -0
  93. dw/server/ui/assets/bicep-B5-_aFwp.js +2 -0
  94. dw/server/ui/assets/cameligo-DMUM7wLl.js +1 -0
  95. dw/server/ui/assets/clojure-Cm7r79vr.js +1 -0
  96. dw/server/ui/assets/codicon-Brq4_Ui5.ttf +0 -0
  97. dw/server/ui/assets/coffee-Ba7i2nA0.js +1 -0
  98. dw/server/ui/assets/cpp-C7h46wYY.js +1 -0
  99. dw/server/ui/assets/csharp-BKxtCVv1.js +1 -0
  100. dw/server/ui/assets/csp-bTuwJoIa.js +1 -0
  101. dw/server/ui/assets/css-DIMkf-bt.js +3 -0
  102. dw/server/ui/assets/css.worker-B3ciXF_0.js +93 -0
  103. dw/server/ui/assets/cssMode-CPznxfY8.js +1 -0
  104. dw/server/ui/assets/cypher-CVaqCwHa.js +1 -0
  105. dw/server/ui/assets/dart-onAF5SnQ.js +1 -0
  106. dw/server/ui/assets/dockerfile-DZFCIeNp.js +1 -0
  107. dw/server/ui/assets/ecl-D05T4iGw.js +1 -0
  108. dw/server/ui/assets/editor-jjEx9u7D.css +1 -0
  109. dw/server/ui/assets/editor.api-CpWcotrd.js +847 -0
  110. dw/server/ui/assets/editor.worker-q-txB4vs.js +30 -0
  111. dw/server/ui/assets/elixir-6RTg0lbw.js +1 -0
  112. dw/server/ui/assets/flow9-C5_-GSwl.js +1 -0
  113. dw/server/ui/assets/freemarker2-CXtRM8N4.js +3 -0
  114. dw/server/ui/assets/fsharp-C8Ef5oNN.js +1 -0
  115. dw/server/ui/assets/go-C-y9NEjX.js +1 -0
  116. dw/server/ui/assets/graphql-fmXr3nnJ.js +1 -0
  117. dw/server/ui/assets/handlebars-N7x-6NMY.js +1 -0
  118. dw/server/ui/assets/hcl-CpzslTdj.js +1 -0
  119. dw/server/ui/assets/html-PhsdjHSr.js +1 -0
  120. dw/server/ui/assets/html.worker-C93Ht9o9.js +506 -0
  121. dw/server/ui/assets/htmlMode-Dgj0SEok.js +1 -0
  122. dw/server/ui/assets/index-3Vw6WAPW.css +1 -0
  123. dw/server/ui/assets/index-DgrYhQd9.js +43 -0
  124. dw/server/ui/assets/ini-sBoK_t0W.js +1 -0
  125. dw/server/ui/assets/java-BEtHBSE6.js +1 -0
  126. dw/server/ui/assets/javascript-BJqN9Qhv.js +1 -0
  127. dw/server/ui/assets/json.worker-B2V3pomh.js +62 -0
  128. dw/server/ui/assets/jsonMode-DbM4SWSv.js +7 -0
  129. dw/server/ui/assets/julia-Bri6UV-V.js +1 -0
  130. dw/server/ui/assets/kotlin-BOotOW0E.js +1 -0
  131. dw/server/ui/assets/less-B9JPFI3C.js +2 -0
  132. dw/server/ui/assets/lexon-CfSJPG6W.js +1 -0
  133. dw/server/ui/assets/liquid-BWr8lEc4.js +1 -0
  134. dw/server/ui/assets/lspLanguageFeatures-C1iGuDyZ.js +4 -0
  135. dw/server/ui/assets/lua-CsQS60Ue.js +1 -0
  136. dw/server/ui/assets/m3-D-oSqn_W.js +1 -0
  137. dw/server/ui/assets/markdown-Cimd5fb3.js +1 -0
  138. dw/server/ui/assets/mdx-DAdMi_0p.js +1 -0
  139. dw/server/ui/assets/mips-CIPQ_RoX.js +1 -0
  140. dw/server/ui/assets/monaco--ixms01u.css +1 -0
  141. dw/server/ui/assets/monaco-BGCeEqaw.js +56 -0
  142. dw/server/ui/assets/msdax-DauUninz.js +1 -0
  143. dw/server/ui/assets/mysql-SOo6toE5.js +1 -0
  144. dw/server/ui/assets/objective-c-FvmIjYaQ.js +1 -0
  145. dw/server/ui/assets/pascal-DrH0SRf2.js +1 -0
  146. dw/server/ui/assets/pascaligo-D-ptJ9y-.js +1 -0
  147. dw/server/ui/assets/perl-oz_6vUea.js +1 -0
  148. dw/server/ui/assets/pgsql-DTj74zXo.js +1 -0
  149. dw/server/ui/assets/php-nr791fC2.js +1 -0
  150. dw/server/ui/assets/pla-CopQ2nXW.js +1 -0
  151. dw/server/ui/assets/postiats-43DmfD33.js +1 -0
  152. dw/server/ui/assets/powerquery-D3hlyOfw.js +1 -0
  153. dw/server/ui/assets/powershell-DmHpPYUd.js +1 -0
  154. dw/server/ui/assets/protobuf-C531GsRP.js +2 -0
  155. dw/server/ui/assets/pug-Z5eAx3Zn.js +1 -0
  156. dw/server/ui/assets/python-Bcn70HdC.js +1 -0
  157. dw/server/ui/assets/qsharp-DkqhCAOL.js +1 -0
  158. dw/server/ui/assets/r-BwWrilGY.js +1 -0
  159. dw/server/ui/assets/razor-D1HmNnby.js +1 -0
  160. dw/server/ui/assets/redis-ClamHrr6.js +1 -0
  161. dw/server/ui/assets/redshift-DT7zqm-g.js +1 -0
  162. dw/server/ui/assets/restructuredtext-BYgofb2h.js +1 -0
  163. dw/server/ui/assets/ruby-DezsRK8O.js +1 -0
  164. dw/server/ui/assets/rust-DdL9SqIa.js +1 -0
  165. dw/server/ui/assets/sb-CcwsVR0C.js +1 -0
  166. dw/server/ui/assets/scala-DHpiXF5c.js +1 -0
  167. dw/server/ui/assets/scheme-BeGwcela.js +1 -0
  168. dw/server/ui/assets/scss-gp-XZpBa.js +3 -0
  169. dw/server/ui/assets/shell-CC2rA5mh.js +1 -0
  170. dw/server/ui/assets/solidity-BEEn4gHE.js +1 -0
  171. dw/server/ui/assets/sophia-CRfGWb83.js +1 -0
  172. dw/server/ui/assets/sparql-D_Lu-MrJ.js +1 -0
  173. dw/server/ui/assets/sql-NEE52Syq.js +1 -0
  174. dw/server/ui/assets/st-DbInun42.js +1 -0
  175. dw/server/ui/assets/swift-Bxkupp3x.js +1 -0
  176. dw/server/ui/assets/systemverilog-Bz4Y3fRF.js +1 -0
  177. dw/server/ui/assets/tcl-DISqw1ZD.js +1 -0
  178. dw/server/ui/assets/ts.worker-D7T1-Ig5.js +67738 -0
  179. dw/server/ui/assets/tsMode-D6u0XmOW.js +11 -0
  180. dw/server/ui/assets/twig-De2hgUGE.js +1 -0
  181. dw/server/ui/assets/typescript-BU6v-LMV.js +1 -0
  182. dw/server/ui/assets/typespec-B8J7ngcE.js +1 -0
  183. dw/server/ui/assets/vb-DV3o63ZY.js +1 -0
  184. dw/server/ui/assets/wgsl-DpFanUEy.js +298 -0
  185. dw/server/ui/assets/workers-Cn7cTUKr.js +1 -0
  186. dw/server/ui/assets/xml--0LP2Lwk.js +1 -0
  187. dw/server/ui/assets/yaml-mpBg9jnt.js +1 -0
  188. dw/server/ui/index.html +17 -0
  189. dw/server/updater.py +192 -0
  190. dw/settings.py +98 -0
  191. dw/shot_span_preflight.py +116 -0
  192. dw/shots.py +359 -0
  193. dw/slice_preflight.py +148 -0
  194. dw/step.py +187 -0
  195. dw/step_cache.py +442 -0
  196. dw/subfolders.py +107 -0
  197. dw/task_domains.py +307 -0
  198. dw/tasks/assess.py +826 -0
  199. dw/tasks/audio_transcription.py +88 -0
  200. dw/tasks/audio_utils.py +1862 -0
  201. dw/tasks/background_remover.py +43 -0
  202. dw/tasks/borders.py +113 -0
  203. dw/tasks/compose_text.py +74 -0
  204. dw/tasks/concat_videos.py +300 -0
  205. dw/tasks/depth_estimator.py +54 -0
  206. dw/tasks/diffusion_upscale.py +109 -0
  207. dw/tasks/dissolve_videos.py +342 -0
  208. dw/tasks/format_messages.py +24 -0
  209. dw/tasks/gather.py +173 -0
  210. dw/tasks/grade.py +97 -0
  211. dw/tasks/image_to_text.py +43 -0
  212. dw/tasks/image_utils.py +764 -0
  213. dw/tasks/interpolate_frames.py +252 -0
  214. dw/tasks/judge.py +68 -0
  215. dw/tasks/model_cache.py +55 -0
  216. dw/tasks/pair_audio.py +268 -0
  217. dw/tasks/qr_code.py +19 -0
  218. dw/tasks/restore_faces.py +175 -0
  219. dw/tasks/rife_model.py +192 -0
  220. dw/tasks/segment.py +121 -0
  221. dw/tasks/select.py +111 -0
  222. dw/tasks/speech_generation.py +228 -0
  223. dw/tasks/stabilize.py +129 -0
  224. dw/tasks/task.py +920 -0
  225. dw/tasks/tensor_image.py +57 -0
  226. dw/tasks/text_generation.py +169 -0
  227. dw/tasks/text_sections.py +80 -0
  228. dw/tasks/upscale.py +203 -0
  229. dw/tasks/video_utils.py +624 -0
  230. dw/tasks/zoe_depth.py +71 -0
  231. dw/teacache.py +381 -0
  232. dw/teacache_models.json +99 -0
  233. dw/test.py +29 -0
  234. dw/type_helpers.py +231 -0
  235. dw/validate.py +68 -0
  236. dw/variable_constraints.py +444 -0
  237. dw/variables.py +443 -0
  238. dw/video_extensions.py +141 -0
  239. dw/vram_estimate.py +116 -0
  240. dw/worker.py +764 -0
  241. dw/workflow.py +2007 -0
  242. dw/workflow_schema.json +1346 -0
  243. dw/workflow_sources.py +383 -0
  244. dw/workflows/h3_context_ir.json +57 -0
  245. dw/workflows/test.json +31 -0
  246. dw/workspace.py +730 -0
  247. dw_mcp/__init__.py +6 -0
  248. dw_mcp/__main__.py +133 -0
  249. dw_mcp/assets.py +336 -0
  250. dw_mcp/authoring.py +114 -0
  251. dw_mcp/catalog.py +360 -0
  252. dw_mcp/client.py +486 -0
  253. dw_mcp/diagnose.py +371 -0
  254. dw_mcp/exports.py +84 -0
  255. dw_mcp/guides.py +35 -0
  256. dw_mcp/media.py +638 -0
  257. dw_mcp/models.py +97 -0
  258. dw_mcp/prompts.py +104 -0
  259. dw_mcp/server.py +1343 -0
  260. dw_mcp/workspaces.py +212 -0
dw_mcp/models.py ADDED
@@ -0,0 +1,97 @@
1
+ """The model cache and the installed diffusers version.
2
+
3
+ Where the rest of the surface spends the GPU, this one spends the disk and
4
+ the network - and, for a delete, spends them in the direction that cannot be
5
+ undone by waiting. Three tools here commit the machine to something a user
6
+ would want to have been asked about first, so each carries its own gate and
7
+ its own reason: a download is measured in tens of gigabytes, a delete throws
8
+ away weights that have to be fetched again, and an update replaces the
9
+ library every pipeline in the install is built on.
10
+
11
+ The refusals deliberately do not share one message. A single "this costs
12
+ something, confirm it" would be wrong for each of them in a different way,
13
+ and a gate the user learns to wave through is not a gate.
14
+ """
15
+
16
+ from dw_mcp.client import DwApiError, api_path
17
+
18
+ DOWNLOAD_REFUSAL = (
19
+ "Downloading a model pulls tens of gigabytes over the network and into "
20
+ "the Hugging Face cache, and it keeps running in the background once "
21
+ "started. Tell the user which repo you are about to fetch and roughly "
22
+ "what it will cost them in disk and bandwidth, get their go-ahead, then "
23
+ "call again with acknowledged_cost=true. `list_models` shows what is "
24
+ "already cached - check there first, the model may not need fetching."
25
+ )
26
+
27
+ DELETE_REFUSAL = (
28
+ "Deleting a cached model removes every downloaded revision of it. "
29
+ "Nothing about this is recoverable locally: getting it back means "
30
+ "downloading it again. Tell the user exactly which repo you are about "
31
+ "to delete and how much it frees, get their go-ahead, then call again "
32
+ "with acknowledged_cost=true."
33
+ )
34
+
35
+ UPDATE_REFUSAL = (
36
+ "Updating diffusers replaces the installed library with GitHub HEAD - "
37
+ "an untagged development build that can break workflows which currently "
38
+ "run, and there is no undo through this tool. Tell the user what is "
39
+ "installed now (`get_diffusers_state`), why the update is worth it, and "
40
+ "get their go-ahead, then call again with acknowledged_cost=true."
41
+ )
42
+
43
+
44
+ def download_model(client, repo_id, acknowledged_cost=False):
45
+ """Start fetching a repo into the Hugging Face cache. Returns as soon as
46
+ the download is started - it does not wait for it to finish."""
47
+ if not acknowledged_cost:
48
+ raise DwApiError(DOWNLOAD_REFUSAL)
49
+ download = client.post_json("/api/models/download", {"repo_id": repo_id})
50
+ return {
51
+ **download,
52
+ "next": "Poll list_downloads for progress. The download continues in "
53
+ "the background; cancel_download stops it.",
54
+ }
55
+
56
+
57
+ def list_downloads(client):
58
+ """Every download the server is running or has recently run."""
59
+ return client.get_json("/api/models/downloads")
60
+
61
+
62
+ def cancel_download(client, download_id):
63
+ """Ask a running download to stop. Not gated: this ends a cost rather
64
+ than starting one, and partial files stay in the cache and resume on a
65
+ retry, so it is cheap to get wrong in the safe direction."""
66
+ return client.post_json(
67
+ api_path("api", "models", "downloads", download_id, "cancel")
68
+ )
69
+
70
+
71
+ def delete_model(client, repo, acknowledged_cost=False):
72
+ """Delete every cached revision of one repo from the hub cache.
73
+
74
+ The server refuses this while a job or a download is active - it would
75
+ be pulling files out from under a reader - and that refusal carries the
76
+ reason, so it reaches the caller unflattened."""
77
+ if not acknowledged_cost:
78
+ raise DwApiError(DELETE_REFUSAL)
79
+ return client.delete_json("/api/models", params={"repo": repo})
80
+
81
+
82
+ def get_diffusers_state(client):
83
+ """The installed diffusers version, its git commit when installed from
84
+ git, and the state of any update in flight."""
85
+ return client.get_json("/api/system/diffusers")
86
+
87
+
88
+ def update_diffusers(client, acknowledged_cost=False):
89
+ """Upgrade diffusers to GitHub HEAD in the background."""
90
+ if not acknowledged_cost:
91
+ raise DwApiError(UPDATE_REFUSAL)
92
+ update = client.post_json("/api/system/diffusers/update")
93
+ return {
94
+ **update,
95
+ "next": "Poll get_diffusers_state for the outcome. The idle worker is "
96
+ "shut down on success so the next job imports the new version.",
97
+ }
dw_mcp/prompts.py ADDED
@@ -0,0 +1,104 @@
1
+ """The stored prompt library: the text a workflow reaches by `prompt:name`.
2
+
3
+ Prompts are the other half of authoring. A workflow argument written as
4
+ `"prompt:sitcom/duke"` resolves against this library at load time, so an
5
+ agent that can write workflows but not prompts can only ever reference text
6
+ somebody else stored.
7
+
8
+ As in `authoring`, validation stays on the server. It already refuses a
9
+ definition that fails the prompt schema and one whose `text` is itself a
10
+ reference - re-checking either here would only give the two a chance to
11
+ disagree.
12
+ """
13
+
14
+ from dw_mcp.client import DwApiError, api_path, coerce_json_object
15
+
16
+ ENHANCE_COST_REFUSAL = (
17
+ "Enhancing a prompt loads a language model and queues a real job on the "
18
+ "engine, which runs one job at a time - it delays any generation waiting "
19
+ "behind it. Tell the user what will be enhanced and with which preset, "
20
+ "get their go-ahead, then call again with acknowledged_cost=true."
21
+ )
22
+
23
+
24
+ def list_prompts(client, tag=None, intended_model=None, include_text=False):
25
+ """The library as a routing table: what each prompt is for, not what it
26
+ says.
27
+
28
+ The bodies are left out by default, which is the same lesson `list_jobs`
29
+ learned - the whole library is 44 prompts and 87 KB, past a client's
30
+ result cap, so a listing that carried them could not be called at all.
31
+ `get_prompt` is where a body comes from once one has been chosen.
32
+ """
33
+ params = {"include_text": "true" if include_text else "false"}
34
+ if tag is not None:
35
+ params["tag"] = tag
36
+ if intended_model is not None:
37
+ params["intended_model"] = intended_model
38
+ return client.get_json("/api/prompts", params=params)
39
+
40
+
41
+ def get_prompt(client, name):
42
+ """One stored prompt's full definition, `name` being the same string a
43
+ workflow would reference it by."""
44
+ return client.get_json(api_path("api", "prompts", name))
45
+
46
+
47
+ def get_prompt_schema(client):
48
+ """The JSON schema a stored prompt must satisfy.
49
+
50
+ Its own route rather than a name under /api/prompts, so a prompt called
51
+ `schema` cannot shadow it.
52
+ """
53
+ return client.get_json("/api/prompt-schema")
54
+
55
+
56
+ def save_prompt(client, name, prompt):
57
+ """Write a prompt into the library, overwriting any prompt of that name.
58
+ The server validates before it writes."""
59
+ prompt = coerce_json_object(prompt, "prompt")
60
+ return client.put_json(api_path("api", "prompts", name), {"prompt": prompt})
61
+
62
+
63
+ def delete_prompt(client, name):
64
+ """Remove a prompt from the library."""
65
+ return client.delete_json(api_path("api", "prompts", name))
66
+
67
+
68
+ def list_enhancers(client):
69
+ """The enhancer presets `enhance_prompt` accepts, with descriptions."""
70
+ return client.get_json("/api/enhancers")
71
+
72
+
73
+ def enhance_prompt(
74
+ client,
75
+ idea,
76
+ preset="h3",
77
+ model_name=None,
78
+ device=None,
79
+ acknowledged_cost=False,
80
+ ):
81
+ """Expand a short idea into a full prompt with a language model.
82
+
83
+ This is queued as an ordinary job, so it is gated like a run and returns
84
+ as soon as it is queued. The enhanced text arrives as the single text
85
+ file in the finished job's manifest.
86
+ """
87
+ if not acknowledged_cost:
88
+ raise DwApiError(ENHANCE_COST_REFUSAL)
89
+ payload = {"idea": idea, "preset": preset}
90
+ # Omitted rather than sent as null: absent means the preset's own default
91
+ # model and a CPU device, which is not what an explicit null would ask for
92
+ if model_name is not None:
93
+ payload["model_name"] = model_name
94
+ if device is not None:
95
+ payload["device"] = device
96
+ job = client.post_json("/api/enhance", payload)
97
+ return {
98
+ "job_id": job.get("id"),
99
+ "status": job.get("status"),
100
+ "queue_position": job.get("queue_position"),
101
+ "next": "Poll get_job(job_id) until it succeeds, then read the text "
102
+ "file in its manifest with get_output_text. Store the result with "
103
+ "save_prompt if it is worth keeping.",
104
+ }