comfy-cli 1.24.0__tar.gz → 1.25.0__tar.gz

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 (300) hide show
  1. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/PKG-INFO +1 -1
  2. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/_lazy.py +56 -1
  3. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cloud/oauth.py +49 -3
  4. comfy_cli-1.25.0/comfy_cli/command/assets_library.py +846 -0
  5. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/cloud_http.py +33 -3
  6. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/app.py +19 -1
  7. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/emit.py +28 -8
  8. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/knowledge.py +14 -5
  9. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/models/models.py +201 -6
  10. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/workflow.py +9 -2
  11. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/workflow_edit.py +70 -10
  12. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/engine.py +396 -62
  13. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/promoted.py +35 -9
  14. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/credentials.py +121 -12
  15. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/discovery.py +2 -0
  16. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/error_codes.py +59 -2
  17. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/knowledge.py +51 -3
  18. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/link_integrity.py +2 -2
  19. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/model_variants.py +6 -2
  20. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/assets_library.json +6 -2
  21. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_push_event.json +1 -1
  22. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy/SKILL.md +4 -3
  23. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/target.py +24 -0
  24. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/workflow_ops.py +648 -45
  25. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/workflow_print.py +30 -5
  26. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/workflow_to_api.py +78 -65
  27. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli.egg-info/PKG-INFO +1 -1
  28. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/pyproject.toml +1 -1
  29. comfy_cli-1.24.0/comfy_cli/command/assets_library.py +0 -338
  30. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/LICENSE +0 -0
  31. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/README.md +0 -0
  32. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/__init__.py +0 -0
  33. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/__main__.py +0 -0
  34. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/_safe_exec.py +0 -0
  35. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/agent/__init__.py +0 -0
  36. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/agent/command.py +0 -0
  37. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/auth/__init__.py +0 -0
  38. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/auth/command.py +0 -0
  39. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/auth/store.py +0 -0
  40. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/builder_api.py +0 -0
  41. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/builder_pagination.py +0 -0
  42. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/caller.py +0 -0
  43. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cancellation.py +0 -0
  44. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cloud/__init__.py +0 -0
  45. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cloud/billing.py +0 -0
  46. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cloud/command.py +0 -0
  47. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cmdline.py +0 -0
  48. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/comfy_client.py +0 -0
  49. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/__init__.py +0 -0
  50. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/_cloud_errors.py +0 -0
  51. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build.py +0 -0
  52. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build_diff.py +0 -0
  53. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build_digest_cache.py +0 -0
  54. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build_package.py +0 -0
  55. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build_paths.py +0 -0
  56. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build_pull.py +0 -0
  57. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build_push.py +0 -0
  58. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build_spec.py +0 -0
  59. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build_targets.py +0 -0
  60. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build_upload_progress.py +0 -0
  61. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/build_validation.py +0 -0
  62. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/code_search.py +0 -0
  63. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/custom_nodes/__init__.py +0 -0
  64. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/custom_nodes/bisect_custom_nodes.py +0 -0
  65. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/custom_nodes/cm_cli_util.py +0 -0
  66. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/custom_nodes/command.py +0 -0
  67. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy.py +0 -0
  68. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_cancel.py +0 -0
  69. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_compute.py +0 -0
  70. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_lifecycle.py +0 -0
  71. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_ls.py +0 -0
  72. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_progress.py +0 -0
  73. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_promote.py +0 -0
  74. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_read.py +0 -0
  75. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_refs.py +0 -0
  76. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_rename.py +0 -0
  77. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_resolve.py +0 -0
  78. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_rollback.py +0 -0
  79. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_run.py +0 -0
  80. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_run_assets.py +0 -0
  81. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_run_watch.py +0 -0
  82. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_runtime.py +0 -0
  83. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_status.py +0 -0
  84. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_types.py +0 -0
  85. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_up.py +0 -0
  86. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/deploy_workflow.py +0 -0
  87. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/__init__.py +0 -0
  88. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/adapters.py +0 -0
  89. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/client.py +0 -0
  90. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/output.py +0 -0
  91. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/poll.py +0 -0
  92. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/schema.py +0 -0
  93. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/spec/openapi.yml +0 -0
  94. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/spec.py +0 -0
  95. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/generate/upload.py +0 -0
  96. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/github/pr_info.py +0 -0
  97. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/install.py +0 -0
  98. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/job_watcher.py +0 -0
  99. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/jobs.py +0 -0
  100. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/launch.py +0 -0
  101. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/models/search.py +0 -0
  102. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/node_deps.py +0 -0
  103. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/nodes.py +0 -0
  104. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/outdated.py +0 -0
  105. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/pack_scan.py +0 -0
  106. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/pr_command.py +0 -0
  107. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/preview.py +0 -0
  108. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/project.py +0 -0
  109. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/run/__init__.py +0 -0
  110. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/run/execution.py +0 -0
  111. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/run/loader.py +0 -0
  112. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/run/preflight.py +0 -0
  113. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/run/watcher.py +0 -0
  114. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/run_cli.py +0 -0
  115. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/setup.py +0 -0
  116. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/stop_port.py +0 -0
  117. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/system.py +0 -0
  118. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/templates.py +0 -0
  119. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/transfer.py +0 -0
  120. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/version_validators.py +0 -0
  121. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command/workflow_fragments.py +0 -0
  122. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/command_mentions.py +0 -0
  123. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/config_manager.py +0 -0
  124. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/constants.py +0 -0
  125. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/__init__.py +0 -0
  126. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/_net.py +0 -0
  127. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/annotations_source.py +0 -0
  128. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/data/__init__.py +0 -0
  129. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/data/cloud_disable_config.yaml +0 -0
  130. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/data/default_text2img.json +0 -0
  131. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/data/supported_nodes.yaml +0 -0
  132. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/default_workflow.py +0 -0
  133. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/errors.py +0 -0
  134. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/loader.py +0 -0
  135. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cql/widget_catalog.py +0 -0
  136. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/cuda_detect.py +0 -0
  137. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/deploy_api.py +0 -0
  138. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/deploy_api_errors.py +0 -0
  139. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/deploy_assets.py +0 -0
  140. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/deploy_download.py +0 -0
  141. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/deploy_events.py +0 -0
  142. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/deploy_jobs.py +0 -0
  143. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/deprecation.py +0 -0
  144. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/download_state.py +0 -0
  145. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/env_checker.py +0 -0
  146. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/execution_errors.py +0 -0
  147. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/file_utils.py +0 -0
  148. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/fragments.py +0 -0
  149. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/git_utils.py +0 -0
  150. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/hardware.py +0 -0
  151. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/hashing.py +0 -0
  152. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/help_json.py +0 -0
  153. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/host_port.py +0 -0
  154. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/http.py +0 -0
  155. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/interaction.py +0 -0
  156. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/jobs_state.py +0 -0
  157. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/layout.py +0 -0
  158. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/layout_quality.py +0 -0
  159. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/local_address.py +0 -0
  160. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/locking.py +0 -0
  161. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/logging.py +0 -0
  162. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/onboarding.py +0 -0
  163. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/output/__init__.py +0 -0
  164. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/output/branding.py +0 -0
  165. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/output/glyphs.py +0 -0
  166. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/output/panels.py +0 -0
  167. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/output/preview.py +0 -0
  168. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/output/progress.py +0 -0
  169. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/output/renderer.py +0 -0
  170. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/output/rich_compat.py +0 -0
  171. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/output/sanitize.py +0 -0
  172. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/pr_cache.py +0 -0
  173. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/project.py +0 -0
  174. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/registry/__init__.py +0 -0
  175. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/registry/api.py +0 -0
  176. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/registry/config_parser.py +0 -0
  177. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/registry/types.py +0 -0
  178. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/resolve_python.py +0 -0
  179. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/__init__.py +0 -0
  180. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/agent.json +0 -0
  181. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/assets.json +0 -0
  182. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/auth.json +0 -0
  183. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_blob_ls.json +0 -0
  184. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_delete.json +0 -0
  185. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_init.json +0 -0
  186. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_ls.json +0 -0
  187. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_pull.json +0 -0
  188. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_push.json +0 -0
  189. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_refs_base_images.json +0 -0
  190. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_refs_build_targets.json +0 -0
  191. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_refs_model_dirs.json +0 -0
  192. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_refs_resolve.json +0 -0
  193. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_release_create.json +0 -0
  194. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_release_delete.json +0 -0
  195. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_release_logs.json +0 -0
  196. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_release_ls.json +0 -0
  197. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_release_manifest.json +0 -0
  198. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_release_show.json +0 -0
  199. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_show.json +0 -0
  200. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_status.json +0 -0
  201. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_update.json +0 -0
  202. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/build_validate.json +0 -0
  203. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/cloud_status.json +0 -0
  204. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_cancel.json +0 -0
  205. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_delete.json +0 -0
  206. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_events.json +0 -0
  207. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_history.json +0 -0
  208. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_logs.json +0 -0
  209. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_ls.json +0 -0
  210. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_progress_event.json +0 -0
  211. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_promote.json +0 -0
  212. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_refs_compute.json +0 -0
  213. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_rename.json +0 -0
  214. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_rollback.json +0 -0
  215. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_run.json +0 -0
  216. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_scale.json +0 -0
  217. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_show.json +0 -0
  218. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_start.json +0 -0
  219. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_status.json +0 -0
  220. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_stop.json +0 -0
  221. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/deploy_up.json +0 -0
  222. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/discover.json +0 -0
  223. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/download.json +0 -0
  224. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/download_status.json +0 -0
  225. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/downloads.json +0 -0
  226. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/env.json +0 -0
  227. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/envelope.json +0 -0
  228. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/error.json +0 -0
  229. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/error_codes.md +0 -0
  230. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/free.json +0 -0
  231. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/generate_list.json +0 -0
  232. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/generate_result.json +0 -0
  233. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/generate_schema.json +0 -0
  234. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/help.json +0 -0
  235. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/jobs.json +0 -0
  236. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/jobs_wait.json +0 -0
  237. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/knowledge.json +0 -0
  238. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/knowledge_block.json +0 -0
  239. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/launch.json +0 -0
  240. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/logs.json +0 -0
  241. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/models.json +0 -0
  242. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/node_deps.json +0 -0
  243. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/nodes.json +0 -0
  244. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/outdated.json +0 -0
  245. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/preview.json +0 -0
  246. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/project.json +0 -0
  247. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/run.json +0 -0
  248. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/run_event.json +0 -0
  249. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/set_default.json +0 -0
  250. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/skill.json +0 -0
  251. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/stop.json +0 -0
  252. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/system_stats.json +0 -0
  253. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/templates.json +0 -0
  254. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/transfer.json +0 -0
  255. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/update.json +0 -0
  256. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/version.json +0 -0
  257. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/which.json +0 -0
  258. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/widget_catalog.json +0 -0
  259. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/schemas/workflow.json +0 -0
  260. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/selector.py +0 -0
  261. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/__init__.py +0 -0
  262. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy/__init__.py +0 -0
  263. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-agent-permissions/SKILL.md +0 -0
  264. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-build/SKILL.md +0 -0
  265. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-build-authoring/SKILL.md +0 -0
  266. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-build-failures/SKILL.md +0 -0
  267. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-build-pins/SKILL.md +0 -0
  268. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes/SKILL.md +0 -0
  269. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes-api-schema/SKILL.md +0 -0
  270. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes-caching/SKILL.md +0 -0
  271. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes-dependencies/SKILL.md +0 -0
  272. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes-frontend/SKILL.md +0 -0
  273. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes-invocation/SKILL.md +0 -0
  274. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes-migration/SKILL.md +0 -0
  275. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes-packaging/SKILL.md +0 -0
  276. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes-search/SKILL.md +0 -0
  277. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes-troubleshooting/SKILL.md +0 -0
  278. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-custom-nodes-validation/SKILL.md +0 -0
  279. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-debug/SKILL.md +0 -0
  280. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-deploy/SKILL.md +0 -0
  281. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-deploy-failures/SKILL.md +0 -0
  282. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-director/SKILL.md +0 -0
  283. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/comfy-relay/SKILL.md +0 -0
  284. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/skills/command.py +0 -0
  285. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/standalone.py +0 -0
  286. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/tracking.py +0 -0
  287. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/typing.py +0 -0
  288. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/ui.py +0 -0
  289. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/update.py +0 -0
  290. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/utils.py +0 -0
  291. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/uv.py +0 -0
  292. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/where.py +0 -0
  293. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli/workspace_manager.py +0 -0
  294. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli.egg-info/SOURCES.txt +0 -0
  295. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli.egg-info/dependency_links.txt +0 -0
  296. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli.egg-info/entry_points.txt +0 -0
  297. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli.egg-info/requires.txt +0 -0
  298. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/comfy_cli.egg-info/top_level.txt +0 -0
  299. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/setup.cfg +0 -0
  300. {comfy_cli-1.24.0 → comfy_cli-1.25.0}/tests/test_file_utils_network.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comfy-cli
3
- Version: 1.24.0
3
+ Version: 1.25.0
4
4
  Summary: A CLI tool for installing and using ComfyUI.
5
5
  Maintainer-email: Yoland Yan <yoland@drip.art>, James Kwon <hongilkwon316@gmail.com>, Robin Huang <robin@drip.art>, "Dr.Lt.Data" <dr.lt.data@gmail.com>
6
6
  License: GPL-3.0-only
@@ -32,7 +32,7 @@ from typing import TYPE_CHECKING, Any
32
32
 
33
33
  import typer
34
34
  from typer.core import TyperGroup
35
- from typer.models import CommandInfo, TyperInfo
35
+ from typer.models import CommandInfo, DefaultPlaceholder, TyperInfo
36
36
 
37
37
  if TYPE_CHECKING:
38
38
  import click
@@ -105,6 +105,60 @@ class LazyCommand:
105
105
  hidden: bool = False
106
106
 
107
107
 
108
+ def _reject_single_callback_app(name: str, spec: LazySubcommand, sub_app: typer.Typer) -> None:
109
+ """Refuse a ``LazySubcommand`` mount of a Typer app that is only a callback.
110
+
111
+ A Typer app with no commands and no subgroups is one function wearing an
112
+ app, and ``add_typer`` turns it into a click ``Group``. A group disables
113
+ interspersed arguments, so the first non-option token ends option parsing
114
+ and everything after it is read as a nested command name. The callback's
115
+ own positional then swallows the query and the trailing flags become a
116
+ subcommand that does not exist::
117
+
118
+ $ comfy code-search KSampler --repo ComfyUI
119
+ Usage: comfy code-search [OPTIONS] {query} COMMAND [ARGS]...
120
+ Error: Missing argument 'query'.
121
+
122
+ while the same flags *before* the query parse fine — the shape a user
123
+ hits only in the installed CLI, since calling the module's app directly
124
+ never exercises the root group. ``code-search`` shipped that way and was
125
+ moved to :class:`LazyCommand`; this keeps the next one from repeating it.
126
+
127
+ A sub-app that supplies its own ``cls`` (e.g. a nested :class:`LazyTyperGroup`
128
+ with its own ``lazy_subcommands`` table) is exempt: its commands are built on
129
+ lookup rather than registered eagerly, so ``registered_commands`` and
130
+ ``registered_groups`` are empty by design, not because it is a bare callback.
131
+ ``cls`` can be set on the app itself (``typer.Typer(cls=...)``) or on its
132
+ callback (``@sub_app.callback(cls=...)``); ``typer.main.solve_typer_info_defaults``
133
+ reads the callback's value first, so this checks both in that order.
134
+ """
135
+ if not isinstance(sub_app, typer.Typer):
136
+ raise TypeError(
137
+ f"lazy_subcommands[{name!r}] names {spec.module}.{spec.attr}, which is "
138
+ f"{sub_app!r}, not a typer.Typer instance."
139
+ )
140
+ if sub_app.registered_commands or sub_app.registered_groups:
141
+ return
142
+ callback = sub_app.registered_callback
143
+ callback_cls = callback.cls if callback is not None else DefaultPlaceholder(None)
144
+ effective_cls = callback_cls if not isinstance(callback_cls, DefaultPlaceholder) else sub_app.info.cls
145
+ if not isinstance(effective_cls, DefaultPlaceholder):
146
+ return
147
+ if sub_app.registered_callback is None:
148
+ raise TypeError(
149
+ f"lazy_subcommands[{name!r}] mounts {spec.module}.{spec.attr} as a command group, but "
150
+ f"that Typer app registers no commands, no subgroups, and no callback — there is nothing "
151
+ f"to mount. Check the module actually registers the commands you expect."
152
+ )
153
+ raise TypeError(
154
+ f"lazy_subcommands[{name!r}] mounts {spec.module}.{spec.attr} as a command group, but that "
155
+ f"Typer app registers no commands and no subgroups — it is a single callback. Mounting it as "
156
+ f"a group makes click demand a nested COMMAND, so options placed after the positional "
157
+ f'argument are rejected. Declare it as LazyCommand({spec.module!r}, attr="<function>") '
158
+ f"instead, naming the callback function rather than the app."
159
+ )
160
+
161
+
108
162
  class LazyTyperGroup(TyperGroup):
109
163
  """Root group with subcommands declared in ``lazy_subcommands`` and built
110
164
  on first lookup. Set the table on a subclass::
@@ -174,6 +228,7 @@ class LazyTyperGroup(TyperGroup):
174
228
 
175
229
  def _build_group(self, name: str, spec: LazySubcommand) -> click.Command:
176
230
  sub_app = getattr(importlib.import_module(spec.module), spec.attr)
231
+ _reject_single_callback_app(name, spec, sub_app)
177
232
  # Same TyperInfo ``add_typer`` would have appended: only the keywords
178
233
  # that were given, so the sub-app's own settings fill the rest.
179
234
  kwargs: dict[str, Any] = {"name": name}
@@ -45,7 +45,7 @@ import urllib.request
45
45
  import webbrowser
46
46
  from dataclasses import dataclass, field
47
47
  from http.server import BaseHTTPRequestHandler
48
- from typing import Any
48
+ from typing import TYPE_CHECKING, Any
49
49
  from urllib.error import HTTPError, URLError
50
50
 
51
51
  from comfy_cli.cloud import (
@@ -56,6 +56,11 @@ from comfy_cli.cloud import (
56
56
  )
57
57
  from comfy_cli.http import NoRedirectHandler, build_http_only_opener
58
58
 
59
+ if TYPE_CHECKING:
60
+ from collections.abc import Callable
61
+
62
+ from comfy_cli.auth.store import CloudSession
63
+
59
64
  # ---------------------------------------------------------------------------
60
65
  # Error types — caller maps these to renderer.error(code=...) codes.
61
66
  # ---------------------------------------------------------------------------
@@ -92,6 +97,19 @@ class OAuthTimeout(OAuthError):
92
97
  code = "oauth_timeout"
93
98
 
94
99
 
100
+ class SessionReplaced(Exception):
101
+ """The stored sign-in is not the one ``ensure_fresh_session(expect=...)`` was asked to refresh.
102
+
103
+ Raised before anything is refreshed, persisted or cleared, so another
104
+ sign-in stored while the caller waited is left exactly as it was.
105
+ ``session`` is the sign-in found in its place.
106
+ """
107
+
108
+ def __init__(self, session: CloudSession) -> None:
109
+ super().__init__("the stored sign-in was replaced by another")
110
+ self.session = session
111
+
112
+
95
113
  # ---------------------------------------------------------------------------
96
114
  # Constants
97
115
  # ---------------------------------------------------------------------------
@@ -758,7 +776,13 @@ def take_last_fatal_refresh_reason() -> str | None:
758
776
  return reason
759
777
 
760
778
 
761
- def ensure_fresh_session(*, leeway_s: int = 60, force: bool = False, allow_clear: bool = True):
779
+ def ensure_fresh_session(
780
+ *,
781
+ leeway_s: int = 60,
782
+ force: bool = False,
783
+ allow_clear: bool = True,
784
+ expect: Callable[[CloudSession], bool] | None = None,
785
+ ):
762
786
  """Return the stored cloud session, refreshing it first when the access
763
787
  token is expired (or within ``leeway_s`` of expiring) and a refresh token
764
788
  is available.
@@ -787,6 +811,13 @@ def ensure_fresh_session(*, leeway_s: int = 60, force: bool = False, allow_clear
787
811
  session lifecycle. The refresh still returns ``None`` so the caller knows it
788
812
  could not freshen the token; it just declines to destroy the shared session.
789
813
 
814
+ ``expect`` is for a caller bound to one sign-in (an upload finished as the
815
+ account that started it). It is called with the stored session on the first
816
+ read and again under the lock, before any refresh, persist or clear; when it
817
+ returns ``False`` another sign-in replaced that one (``comfy cloud login`` in
818
+ another shell), so :class:`SessionReplaced` is raised and the store is left
819
+ untouched. Without it every stored session is refreshed, as before.
820
+
790
821
  Concurrency: the auth server rotates the refresh token on every refresh and
791
822
  invalidates the old one. A parallel ``comfy run`` fan-out (plus background
792
823
  ``jobs watch`` processes) would otherwise have N processes each load the
@@ -800,6 +831,8 @@ def ensure_fresh_session(*, leeway_s: int = 60, force: bool = False, allow_clear
800
831
  from comfy_cli.auth import store as auth_store
801
832
 
802
833
  session = auth_store.get_cloud_session()
834
+ if session is not None and expect is not None and not expect(session):
835
+ raise SessionReplaced(session)
803
836
  if session is None or not session.refresh_token:
804
837
  return session
805
838
  if not force and not session.is_expired(leeway_s=leeway_s):
@@ -821,6 +854,7 @@ def ensure_fresh_session(*, leeway_s: int = 60, force: bool = False, allow_clear
821
854
  leeway_s=leeway_s,
822
855
  force=force,
823
856
  allow_clear=allow_clear,
857
+ expect=expect,
824
858
  )
825
859
  except TimeoutError:
826
860
  # A peer has held the lock longer than a refresh should take. Don't
@@ -833,7 +867,15 @@ def ensure_fresh_session(*, leeway_s: int = 60, force: bool = False, allow_clear
833
867
  return session
834
868
 
835
869
 
836
- def _locked_refresh(auth_store, *, observed_refresh_token: str, leeway_s: int, force: bool, allow_clear: bool = True):
870
+ def _locked_refresh(
871
+ auth_store,
872
+ *,
873
+ observed_refresh_token: str,
874
+ leeway_s: int,
875
+ force: bool,
876
+ allow_clear: bool = True,
877
+ expect: Callable[[CloudSession], bool] | None = None,
878
+ ):
837
879
  """Decide → POST → persist, executed while holding the secrets lock.
838
880
 
839
881
  Re-reads the persisted session first (double-checked locking): if a peer
@@ -841,6 +883,10 @@ def _locked_refresh(auth_store, *, observed_refresh_token: str, leeway_s: int, f
841
883
  one rather than spending the now-consumed token we observed before locking.
842
884
  """
843
885
  session = auth_store.get_cloud_session()
886
+ # Checked under the lock: another login stored since the first read is
887
+ # neither refreshed nor cleared on this caller's behalf.
888
+ if session is not None and expect is not None and not expect(session):
889
+ raise SessionReplaced(session)
844
890
  if session is None or not session.refresh_token:
845
891
  return session
846
892