gflow-cli 0.14.0__tar.gz → 0.15.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.
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/CHANGELOG.md +37 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/PKG-INFO +2 -2
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/PROJECT_STATUS.md +4 -2
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/USAGE.md +45 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/pyproject.toml +3 -3
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/__init__.py +1 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/image.py +18 -2
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/transports/ui_automation.py +126 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/transports/ui_automation_video.py +17 -6
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/cli_image.py +155 -13
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/recorder.py +6 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_image.py +58 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_ui_automation.py +166 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_image.py +289 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/test_image_steps.py +1 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/uv.lock +25 -25
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/active.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/branch-review.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/changelog.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/check.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/doc-review.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/known-issues.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/next.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/plan.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/pr-council-review.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/predict.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/release.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/scenario.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.claude/commands/gflow/status.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.continue-here.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.env.template +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.gitattributes +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.github/CODEOWNERS +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.github/copilot-instructions.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.github/dependabot.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.github/workflows/ci.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.github/workflows/external-pr-triage.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.github/workflows/governance-advisory.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.github/workflows/governance-benchmark.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.github/workflows/release.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.gitignore +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.gitleaks.toml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.pre-commit-config.yaml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/.secrets.baseline +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/AGENTS.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/CLAUDE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/CONFIGURATION.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/CONTRIBUTING.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/DISCLAIMER.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/GEMINI.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/KNOWN_ISSUES.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/LICENSE +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/PLAN.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/PR162_MOVIE_CHARACTER_REVIEW.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/RELEASE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/ROADMAP.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/conftest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docker-compose.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/AGENT_GUIDE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/ARCHITECTURE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/AUTHENTICATION.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/CHARACTER.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/CHARACTER_RECON.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/CONFIGURATION.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/DATA_LAYER.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/DEBUGGING.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/DEMOS.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/DEVELOPMENT.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/E2E_TESTING.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/EXTERNAL_STORAGE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/GITHUB.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/GOVERNANCE_BENCHMARK.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/INDEX.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_data_layer.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_image_batch.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_v0.10.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_v0.11.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_v0.12.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_v0.13.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_v0.7.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_v0.8.1.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_v0.9.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_v0.9.1.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/LIVE_VERIFICATION_video_download.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/MOVIE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/SECURITY.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/USER_GUIDE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/assets/demo-split-pf.gif +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/assets/example-run.gif +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/schemas/movie-handoff.schema.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/superpowers/2026-05-17-issue-15-handover.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/superpowers/character-scenario.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/superpowers/plans/2026-06-01-governance-enforcement-advisory/PLAN.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/superpowers/plans/2026-06-04-character-create-recording.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/superpowers/plans/2026-06-06-movie-p0-asyncio-hotfix.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/superpowers/plans/2026-06-06-movie-p1-composition-manifest.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/superpowers/plans/2026-06-06-movie-p2-native-identity-voice.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/superpowers/specs/2026-06-06-movie-consistency-design.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/examples/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/examples/batch_from_config.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/examples/multi_prompt_t2i.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/examples/sample_config.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/examples/sample_prompts.txt +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/examples/single_image_t2i.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/examples/workflow_chain.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/llms.txt +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/01_upload_image.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/04_archive_workflow.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/05_createProject.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/06_batchGenerateImages.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/08_batchAsyncGenerateVideoStartAndEndImage.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/09_batchAsyncGenerateVideoReferenceImages.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/10_batchCheckAsyncVideoGenerationStatus_successful.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/11_batchCheckAsyncVideoGenerationStatus_failed.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/12_create_scene.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/13_sceneWorkflows_update.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/14_get_scene_workflows.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/samples/captured/15_commit_flowWorkflow.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/ci/check_doc_links.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/ci/check_materiality.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/ci/check_repo_hygiene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/debug_editor.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/debug_gen_settings.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/debug_settings.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/_recording_client.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/_spike_common.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/active_plan.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/capture_i2v_frame_slots_dom.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/capture_i2v_intercept_submit.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/capture_i2v_model_select_repro.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/capture_i2v_post_bind_state.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/capture_image_add_media_dom.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/capture_locale_invariants.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/cdp_drive_and_probe.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/character_create_spike.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/character_create_spike_v2.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/dump_character_selectors.js +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/make_project.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/materiality_backtest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/monitor_pr_38.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/patch_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/record_flow_capture.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/skillopt/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/skillopt/harness.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/skillopt/tasks.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/spike_char_editor_dom.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/spike_char_gen_capture.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/spike_movie_attach_payload.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/spike_movie_entity_recon.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/spike_movie_gen_capture.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/spike_movie_picker_select.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/spike_movie_voice_list.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/dev/spike_patch_entity.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/diag_capture_flow_traffic.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/diag_recaptcha_mint.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/record_demo.ps1 +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/smoke_image.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/smoke_real_chrome_image.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/smoke_video_editor.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/smoke_worker_style.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/scripts/verify_chrome_auth_viability.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/skills/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/skills/gflow-cli/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/skills/plan/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/skills/pr-council-review/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/skills/predict/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/skills/scenario/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/skills/status/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/sonar-project.properties +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/__main__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/_cli_helpers.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/_retry.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/_sapisidhash.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/client.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/dto.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/recaptcha.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/routes.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/scene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/transports/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/transports/_common.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/transports/base.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/transports/experimental/bearer.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/transports/experimental/sapisidhash.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/api/video.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/auth/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/auth/base.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/auth/factory.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/auth/internal_chromium.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/auth/real_chrome.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/auth/strategies.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/auth/verification.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/browser_manager.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/chain.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/chain_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/cli.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/cli_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/cli_data.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/cli_models.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/cli_movie.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/cli_run.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/cli_scene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/cli_video.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/composition.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/config.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/chain_repo.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/migrations/0001_initial.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/migrations/0002_add_cloud_storage.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/migrations/0003_add_scene_tables.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/migrations/0004_add_scene_output_path.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/migrations/0005_add_chain_links.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/migrations/0006_add_operations_metadata.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/migrations/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/models.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/queries.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/redaction.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/repository.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/data/store.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/errors.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/exceptions.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/image_batch.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/json_output.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/media.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/movie_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/observability.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/paths.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/profile_store.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/services/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/services/character_create.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/src/gflow_cli/storage.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tasks/lessons.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/test_assets/sample_batch.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/test_assets/sample_batch.tsv +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/test_assets/sample_batch_invalid.tsv +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/fixtures/character_gen_response.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/fixtures/patch_entity_response.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_aisandbox_auth_error.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_aisandbox_auth_headers.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_bearer_redaction.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_client.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_client_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_client_delete_characters.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_client_generate_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_client_image.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_client_launch_kwargs.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_client_patch_entity.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_client_scene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_concurrency.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_dto.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_image_dto.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_post_json_aisandbox_auth.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_recaptcha.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_retry.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_routes.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_routes_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_routes_scene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_sapisidhash_helper.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_scene_models.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_video.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/test_video_request.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_base.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_bearer.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_common.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_evaluate_fetch.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_factory.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_fingerprint.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_sapisidhash.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_transport_timeout.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_ui_automation_batch.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_ui_automation_image_mode.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_ui_automation_video.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/api/transports/test_ui_character_editor.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/auth/strategies/test_factory.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/auth/strategies/test_strategies.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/auth/test_verification.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_auth_list.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_character_create.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_data.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_image_seed_removed.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_models.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_movie.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_run.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_scene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_video.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_cli_video_chain.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_error_handling.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_helpers.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_movie_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/cli/test_t2i_multi_prompt.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/composition/test_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/composition/test_compose_prompt.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/composition/test_handoff.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/conftest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_chain_repo.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_find_incomplete_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_models.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_packaging.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_recorder.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_recorder_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_redaction.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_repository.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_scene_persistence.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_settings_and_errors.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/data/test_store_migrations.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/dev/test_record_flow_capture.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/dev/test_recording_client.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/conftest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_aisandbox_auth_live.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_auth_verification_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_chain_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_character_create_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_data_layer_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_i2v_flags_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_image_batch_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_image_i2i_ref_cap_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_json_output_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_locale_selectors_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_scene_compose_live.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_transports_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_video_r2v_ref_cap_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/e2e/test_video_t2v_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/auth.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/auth_login.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/character_create.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/character_read.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/conftest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/image.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/test_auth_login_steps.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/test_auth_steps.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/test_character_create_steps.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/test_character_read_steps.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/test_step_collision_guard.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/test_video_chain_steps.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/features/video_chain.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/fixtures/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/fixtures/seeded_catalog.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/image_batch/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/image_batch/test_image_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/image_batch/test_observability_events.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/integration/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/integration/conftest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/integration/constants.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/integration/test_storage_gcs.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/integration/test_storage_s3.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/scripts/test_capture_locale_invariants.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/scripts/test_check_materiality.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/scripts/test_check_repo_hygiene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/scripts/test_materiality_backtest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/services/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/services/test_character_create_redaction.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/services/test_character_create_saga.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/services/test_character_gen_no_direct_post.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/smoke/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/smoke/test_profile_account_smoke.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/smoke/test_real_flow.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_auth.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_browser_manager.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_chain.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_chain_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_cli_data.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_config.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_conftest_isolation.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_data_queries.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_documentation_gate.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_errors.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_errors_403.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_json_output.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_marker_registry.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_media.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_observability.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_paths.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_profile_store.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.0}/tests/test_smoke.py +0 -0
|
@@ -7,6 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.15.0] — 2026-06-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`gflow image` can reference locked CHARACTER entities** for character-consistent
|
|
15
|
+
stills. New `--reference-entity <id>` (repeatable) + `--reference-entity-name` on
|
|
16
|
+
`image t2i` / `i2i`, plus `--project <id>` to generate in an EXISTING project (where
|
|
17
|
+
the entities live) instead of a throwaway scratch project. Entities attach through
|
|
18
|
+
the editor's **Personagens picker** and ride the submit as `referenceEntities`
|
|
19
|
+
(confirmed against the live API); `_build_batch_generate_images_body` serializes them
|
|
20
|
+
so non-UI/headless transports get parity too. Entities count toward the per-model
|
|
21
|
+
reference cap. `--project` / `--reference-entity` are single-prompt only; for a pure
|
|
22
|
+
character reference use `t2i` (`i2i` still needs a `--ref`). See `docs/USAGE.md` →
|
|
23
|
+
"Character-consistent images (entity references)".
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- `--project` no longer overwrites an existing project's stored title/source in the
|
|
28
|
+
local history DB (the recorder preserves the curated title for non-created projects).
|
|
29
|
+
|
|
30
|
+
### Security
|
|
31
|
+
|
|
32
|
+
- `--project` / `--reference-entity` ids are validated at the CLI boundary
|
|
33
|
+
(`[A-Za-z0-9-]{1,128}`), closing an unvalidated `page.goto` navigation path
|
|
34
|
+
(`project_editor_url` lacked the allowlist its sibling routes enforce) and a
|
|
35
|
+
CSS-selector injection vector (`data-tile-id='fe_id_<id>'`). The request-body debug
|
|
36
|
+
logger elides large reference-field values so Flow-built image bytes can't leak into
|
|
37
|
+
logs.
|
|
38
|
+
|
|
39
|
+
### Internal
|
|
40
|
+
|
|
41
|
+
- Bump dev/CI `ruff` to `0.15.16` (both the `dev` extra and the `dependency-groups`
|
|
42
|
+
pin; supersedes Dependabot PR #165, which updated only the soft `>=` extra and not
|
|
43
|
+
the hard `==` group pin CI actually uses). `ruff check` / `format --check` clean.
|
|
44
|
+
|
|
10
45
|
## [0.14.0] — 2026-06-07
|
|
11
46
|
|
|
12
47
|
### Added
|
|
@@ -1434,7 +1469,8 @@ shell-script template that branches on these codes.
|
|
|
1434
1469
|
|
|
1435
1470
|
First skeleton. Not functional end-to-end yet.
|
|
1436
1471
|
|
|
1437
|
-
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.
|
|
1472
|
+
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.15.0...HEAD
|
|
1473
|
+
[0.15.0]: https://github.com/ffroliva/gflow-cli/compare/v0.14.0...v0.15.0
|
|
1438
1474
|
[0.14.0]: https://github.com/ffroliva/gflow-cli/compare/v0.13.0...v0.14.0
|
|
1439
1475
|
[0.13.0]: https://github.com/ffroliva/gflow-cli/compare/v0.12.0...v0.13.0
|
|
1440
1476
|
[0.12.0]: https://github.com/ffroliva/gflow-cli/compare/v0.11.0...v0.12.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gflow-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.15.0
|
|
4
4
|
Summary: Unofficial CLI for Google Flow — drive Veo image-to-video generations from the terminal.
|
|
5
5
|
Project-URL: Homepage, https://github.com/ffroliva/gflow-cli
|
|
6
6
|
Project-URL: Issues, https://github.com/ffroliva/gflow-cli/issues
|
|
@@ -53,7 +53,7 @@ Requires-Dist: numpy>=1.24; extra == 'dev'
|
|
|
53
53
|
Requires-Dist: pyright>=1.1.0; extra == 'dev'
|
|
54
54
|
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
55
55
|
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
56
|
-
Requires-Dist: ruff>=0.15.
|
|
56
|
+
Requires-Dist: ruff>=0.15.16; extra == 'dev'
|
|
57
57
|
Provides-Extra: gcs
|
|
58
58
|
Requires-Dist: gcsfs>=2024.2.0; extra == 'gcs'
|
|
59
59
|
Requires-Dist: universal-pathlib>=0.2.5; extra == 'gcs'
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
## Current release
|
|
6
6
|
|
|
7
|
-
**v0.
|
|
7
|
+
**v0.15.0 — alpha.** **Character-consistent images via entity references.** `gflow image t2i/i2i` can now reference locked Flow CHARACTER entities (`--reference-entity <id>`, repeatable) and generate in an existing project (`--project <id>`) where those entities live — entities attach through the editor's Personagens picker and ride the submit as `referenceEntities` (confirmed against the live API; the body builder serializes them for headless transports too). Live-verified 2026-06-08: a 3-frame Dragon-Hook smoke rendered drift-free with all three characters on-model. LLM-council-reviewed (security/correctness/dedup) before merge. Carries forward the v0.14.0 `gflow movie` line (multi-scene, character-consistent video).
|
|
8
8
|
|
|
9
|
-
**Develop (unreleased, post-v0.
|
|
9
|
+
**Develop (unreleased, post-v0.15.0):** *(empty — develop is the staging branch for the next release).*
|
|
10
10
|
|
|
11
11
|
## Milestone history
|
|
12
12
|
|
|
@@ -52,6 +52,8 @@
|
|
|
52
52
|
| `gflow character rm` — free character deletion (#150) | ✅ done (v0.13.0) |
|
|
53
53
|
| Align I2V CLI flags with Flow UI Labels (`--initial-frame`) (#122) | ✅ done (v0.13.0) |
|
|
54
54
|
| In-project governance (ruff T20, materiality Classifier) | ✅ done (v0.13.0) |
|
|
55
|
+
| `gflow movie` — multi-scene, character-consistent video from a TOML manifest (entity reuse, resumable, handoff manifest) | ✅ done (v0.14.0) |
|
|
56
|
+
| `gflow image t2i/i2i` — reference locked CHARACTER entities (`--reference-entity`) + `--project` for character-consistent stills | ✅ done (v0.15.0) |
|
|
55
57
|
| `gflow character` — reusable Flow Character entities (`create`/`list`/`show`/`voices`), persist-before-spend saga (#145) | ✅ done (v0.12.0) |
|
|
56
58
|
| `gflow scene` — Add Clip / Scenes compose + credit-free server-side extended video (`runVideoFxConcatenation`) | ✅ done (v0.12.0) |
|
|
57
59
|
| `gflow video chain` — last-frame I2V chaining from a JSONL manifest (`--dry-run`/`--max-links`/`--resume-from`) | ✅ done (v0.12.0) |
|
|
@@ -131,6 +131,13 @@ Options:
|
|
|
131
131
|
Aspect ratio. [default: 9:16]
|
|
132
132
|
-n, --count INTEGER How many images to generate (1-4). [default: 1]
|
|
133
133
|
--out PATH Output directory (see "Output paths" below).
|
|
134
|
+
--project ID Generate in this EXISTING Flow project instead of a
|
|
135
|
+
scratch project. Required to reference locked
|
|
136
|
+
entities/assets in that project. Single-prompt only.
|
|
137
|
+
--reference-entity ID Flow CHARACTER entity id to reference for character
|
|
138
|
+
consistency (repeatable; must live in --project).
|
|
139
|
+
Single-prompt only.
|
|
140
|
+
--reference-entity-name N Display name paired with --reference-entity.
|
|
134
141
|
--profile NAME Profile name (overrides default).
|
|
135
142
|
```
|
|
136
143
|
|
|
@@ -212,6 +219,10 @@ Options:
|
|
|
212
219
|
Aspect ratio. [default: 9:16]
|
|
213
220
|
-n, --count INTEGER How many images to generate (1-4). [default: 1]
|
|
214
221
|
--out PATH Output directory (same semantics as t2i).
|
|
222
|
+
--project ID Generate in this EXISTING Flow project (skip scratch).
|
|
223
|
+
--reference-entity ID Flow CHARACTER entity id to reference (repeatable;
|
|
224
|
+
must live in --project). Counts toward the ref cap.
|
|
225
|
+
--reference-entity-name N Display name paired with --reference-entity.
|
|
215
226
|
--profile NAME Profile name (overrides default).
|
|
216
227
|
```
|
|
217
228
|
|
|
@@ -248,6 +259,40 @@ A 2-image run produces files numbered `_1.png`, `_2.png`:
|
|
|
248
259
|
./variants/<media_name_b>_2.png
|
|
249
260
|
```
|
|
250
261
|
|
|
262
|
+
## Character-consistent images (entity references)
|
|
263
|
+
|
|
264
|
+
`--reference-entity` makes `image t2i`/`i2i` reference a locked Flow **CHARACTER
|
|
265
|
+
entity** (minted via `gflow character create`) so the generated subject stays
|
|
266
|
+
on-model across shots — no per-shot prompt wrangling or fragile image refs.
|
|
267
|
+
|
|
268
|
+
How it works: entities are **project-scoped**, so you must generate **in the
|
|
269
|
+
project that owns them** via `--project <id>` (this also means no throwaway
|
|
270
|
+
scratch project is created). The CLI attaches each entity through the Flow editor's
|
|
271
|
+
resource picker; the submit then carries `referenceEntities`, exactly like the
|
|
272
|
+
video R2V path. Entities count toward the same per-model reference cap as `--ref`
|
|
273
|
+
images. `--reference-entity` / `--project` are **single-prompt only**.
|
|
274
|
+
|
|
275
|
+
For a *pure* character reference (no starting image) use `t2i` — `i2i` still
|
|
276
|
+
requires at least one `--ref`.
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
# One locked character, consistent across runs (t2i = no image ref needed)
|
|
280
|
+
gflow image t2i "Aria explores a neon market, full body" \
|
|
281
|
+
--project 7fa97443-… --reference-entity 8a77f8cb-… --reference-entity-name Aria \
|
|
282
|
+
--model nano2 --aspect 9:16 -n 3
|
|
283
|
+
|
|
284
|
+
# Several characters in one scene (each --reference-entity repeatable)
|
|
285
|
+
gflow image t2i "Aria and Drako meet at the gate" --project 7fa97443-… \
|
|
286
|
+
--reference-entity 8a77f8cb-… --reference-entity 4ed5cb7f-…
|
|
287
|
+
|
|
288
|
+
# i2i: a starting image PLUS an entity for the character
|
|
289
|
+
gflow image i2i "place this hero in a snowy pass" --ref hero.png \
|
|
290
|
+
--project 7fa97443-… --reference-entity 8a77f8cb-…
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
> Ids are validated at the CLI boundary (letters/digits/hyphens, ≤128 chars).
|
|
294
|
+
> The entity must already exist in `--project` (see `gflow character create`).
|
|
295
|
+
|
|
251
296
|
## `gflow image batch`
|
|
252
297
|
|
|
253
298
|
Generate multiple images from a single manifest file. The format is dispatched by file extension (`.json` or `.tsv`).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "gflow-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.15.0"
|
|
4
4
|
description = "Unofficial CLI for Google Flow — drive Veo image-to-video generations from the terminal."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { file = "LICENSE" }
|
|
@@ -33,7 +33,7 @@ dependencies = [
|
|
|
33
33
|
dev = [
|
|
34
34
|
"pytest>=8.0.0",
|
|
35
35
|
"pytest-asyncio>=0.23.0",
|
|
36
|
-
"ruff>=0.15.
|
|
36
|
+
"ruff>=0.15.16",
|
|
37
37
|
"pyright>=1.1.0",
|
|
38
38
|
# video-chain: the last-frame extractor (media.py) decodes with PyAV, and its
|
|
39
39
|
# tests build synthetic mp4 fixtures with numpy. Declared here so the dev/CI
|
|
@@ -134,7 +134,7 @@ dev = [
|
|
|
134
134
|
"pytest-asyncio>=1.3.0",
|
|
135
135
|
"pytest-bdd>=8.1.0",
|
|
136
136
|
"pytest-cov>=7.1.0",
|
|
137
|
-
"ruff==0.15.
|
|
137
|
+
"ruff==0.15.16",
|
|
138
138
|
]
|
|
139
139
|
# Container-based integration tests — requires Docker daemon.
|
|
140
140
|
# Install: uv sync --group containers
|
|
@@ -229,6 +229,14 @@ class GenerateImageRequest:
|
|
|
229
229
|
# dialog by the ui_automation transport (the REST uploadImage path 401s).
|
|
230
230
|
# The common i2i case; `refs` (pre-uploaded UUIDs) would need library-select.
|
|
231
231
|
ref_paths: tuple[Path, ...] = ()
|
|
232
|
+
# Flow CHARACTER entity ids to reference (project-scoped, attached via the
|
|
233
|
+
# Add-Media → Personagens picker by the ui_automation transport). Entities
|
|
234
|
+
# keep generated subjects consistent with a locked character. They count
|
|
235
|
+
# toward the same per-model reference cap as image refs.
|
|
236
|
+
reference_entities: tuple[str, ...] = ()
|
|
237
|
+
# Optional display names paired with reference_entities (used by the UI
|
|
238
|
+
# picker when an id-keyed tile can't be located by id alone).
|
|
239
|
+
reference_entity_names: tuple[str, ...] = ()
|
|
232
240
|
recaptcha_token: str = "" # populated by caller right before send; "" means unminted
|
|
233
241
|
# number of images to generate (1–4); UI transport uses this to set Flow's count tab
|
|
234
242
|
count: int = 1
|
|
@@ -240,10 +248,10 @@ class GenerateImageRequest:
|
|
|
240
248
|
if not 1 <= self.count <= 4:
|
|
241
249
|
msg = f"GenerateImageRequest.count must be 1–4, got {self.count}"
|
|
242
250
|
raise ValueError(msg)
|
|
243
|
-
n_refs = len(self.refs) + len(self.ref_paths)
|
|
251
|
+
n_refs = len(self.refs) + len(self.ref_paths) + len(self.reference_entities)
|
|
244
252
|
cap = reference_cap_for(self.model)
|
|
245
253
|
if n_refs > cap:
|
|
246
|
-
msg = f"{self.model.value} allows at most {cap} reference
|
|
254
|
+
msg = f"{self.model.value} allows at most {cap} reference(s); got {n_refs}"
|
|
247
255
|
raise ValueError(
|
|
248
256
|
msg,
|
|
249
257
|
)
|
|
@@ -299,6 +307,14 @@ def _build_batch_generate_images_body(
|
|
|
299
307
|
# Always present — empty list for T2I, populated for I2I.
|
|
300
308
|
"imageInputs": [r.to_wire() for r in req.refs],
|
|
301
309
|
}
|
|
310
|
+
# Character entity references. Shape confirmed by live capture (2026-06-08):
|
|
311
|
+
# the image submit carries `referenceEntities: [{"entityId": <id>}]`. Added
|
|
312
|
+
# only when present so plain t2i/i2i bodies stay byte-identical to the
|
|
313
|
+
# captured samples. The ui_automation transport attaches entities via the
|
|
314
|
+
# Personagens picker and lets Flow's JS build this; non-UI transports rely
|
|
315
|
+
# on this serialization.
|
|
316
|
+
if req.reference_entities:
|
|
317
|
+
request["referenceEntities"] = [{"entityId": e} for e in req.reference_entities]
|
|
302
318
|
return {
|
|
303
319
|
"clientContext": cc,
|
|
304
320
|
"mediaGenerationContext": {"batchId": batch_id},
|
|
@@ -31,6 +31,7 @@ from gflow_cli.api.transports._common import extract_project_id
|
|
|
31
31
|
from gflow_cli.api.transports.ui_automation_video import (
|
|
32
32
|
MODE_SWITCH_TRIGGER_SELECTORS,
|
|
33
33
|
VideoGenerationMixin,
|
|
34
|
+
zip_entity_refs,
|
|
34
35
|
)
|
|
35
36
|
from gflow_cli.errors import (
|
|
36
37
|
AuthExpiredError,
|
|
@@ -518,6 +519,70 @@ def _images_from_responses(
|
|
|
518
519
|
return images, first_error_status, first_error_route
|
|
519
520
|
|
|
520
521
|
|
|
522
|
+
_REF_VALUE_MAX_CHARS = 512
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
def _elide_large_value(value: Any) -> Any:
|
|
526
|
+
"""Return *value* verbatim when small, else a length-only redaction marker.
|
|
527
|
+
|
|
528
|
+
Guards the request-body logger against dumping large/secret payloads: if Flow
|
|
529
|
+
names an i2i image field `reference*`/`*entity*`, its base64 bytes would match
|
|
530
|
+
the reference-field filter and be logged in full. Small fields like
|
|
531
|
+
`referenceEntities` (a short list of `{entityId}`) pass through; anything
|
|
532
|
+
serializing beyond the cap is elided to a `<elided N chars>` marker.
|
|
533
|
+
"""
|
|
534
|
+
try:
|
|
535
|
+
serialized = json.dumps(value, default=str)
|
|
536
|
+
except (TypeError, ValueError):
|
|
537
|
+
return f"<unserializable {type(value).__name__}>"
|
|
538
|
+
if len(serialized) > _REF_VALUE_MAX_CHARS:
|
|
539
|
+
return f"<elided {len(serialized)} chars>"
|
|
540
|
+
return value
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
def _summarize_batch_request_body(post_data: str | None) -> dict[str, Any]:
|
|
544
|
+
"""Compact, byte-safe summary of an outgoing ``batchGenerateImages`` body.
|
|
545
|
+
|
|
546
|
+
This is the make-or-break signal for the entity-reference spike: it reveals
|
|
547
|
+
whether Flow's image submit carries a ``referenceEntities`` field after we
|
|
548
|
+
attach a character via the picker — WITHOUT logging the full body (i2i
|
|
549
|
+
bodies embed base64 image bytes that would flood the log and leak content).
|
|
550
|
+
|
|
551
|
+
Returns a dict with ``present``, ``mentions_reference_entities`` (cheap
|
|
552
|
+
substring probe that survives non-JSON bodies), and — when the body parses —
|
|
553
|
+
the keys of ``requests[0]`` plus any reference/entity-related fields verbatim
|
|
554
|
+
(those are small id lists, safe to surface).
|
|
555
|
+
"""
|
|
556
|
+
if not post_data:
|
|
557
|
+
return {"present": False}
|
|
558
|
+
summary: dict[str, Any] = {
|
|
559
|
+
"present": True,
|
|
560
|
+
"bytes": len(post_data),
|
|
561
|
+
"mentions_reference_entities": "referenceEntit" in post_data,
|
|
562
|
+
}
|
|
563
|
+
try:
|
|
564
|
+
parsed: object = json.loads(post_data)
|
|
565
|
+
except (ValueError, TypeError):
|
|
566
|
+
return summary
|
|
567
|
+
if not isinstance(parsed, dict):
|
|
568
|
+
return summary
|
|
569
|
+
parsed_dict = cast("dict[str, Any]", parsed)
|
|
570
|
+
reqs = parsed_dict.get("requests")
|
|
571
|
+
if isinstance(reqs, list) and reqs and isinstance(reqs[0], dict):
|
|
572
|
+
first = cast("dict[str, Any]", reqs[0])
|
|
573
|
+
summary["request0_keys"] = sorted(first.keys())
|
|
574
|
+
ref_bits = {
|
|
575
|
+
k: _elide_large_value(v)
|
|
576
|
+
for k, v in first.items()
|
|
577
|
+
if "reference" in k.lower() or "entity" in k.lower()
|
|
578
|
+
}
|
|
579
|
+
if ref_bits:
|
|
580
|
+
summary["reference_fields"] = ref_bits
|
|
581
|
+
else:
|
|
582
|
+
summary["top_keys"] = sorted(parsed_dict.keys())
|
|
583
|
+
return summary
|
|
584
|
+
|
|
585
|
+
|
|
521
586
|
class UiAutomationTransport(VideoGenerationMixin):
|
|
522
587
|
"""D.2.4 — Playwright UI mimicry strategy.
|
|
523
588
|
|
|
@@ -1593,6 +1658,51 @@ class UiAutomationTransport(VideoGenerationMixin):
|
|
|
1593
1658
|
|
|
1594
1659
|
return captured, detach
|
|
1595
1660
|
|
|
1661
|
+
@staticmethod
|
|
1662
|
+
def _attach_batch_request_logger(
|
|
1663
|
+
page: Page,
|
|
1664
|
+
*,
|
|
1665
|
+
project_id: str | None = None,
|
|
1666
|
+
) -> Callable[[], None]:
|
|
1667
|
+
"""Register a ``page.on('request', ...)`` that logs a compact summary of
|
|
1668
|
+
each outgoing ``batchGenerateImages`` body.
|
|
1669
|
+
|
|
1670
|
+
The summary (see :func:`_summarize_batch_request_body`) surfaces whether
|
|
1671
|
+
the submit carries ``referenceEntities`` — the entity-reference spike's
|
|
1672
|
+
make-or-break signal — without dumping i2i image bytes. Returns an
|
|
1673
|
+
idempotent detach fn, torn down alongside the response listener.
|
|
1674
|
+
"""
|
|
1675
|
+
|
|
1676
|
+
def on_request(request_obj: Any) -> None:
|
|
1677
|
+
if "batchGenerateImages" not in request_obj.url:
|
|
1678
|
+
return
|
|
1679
|
+
try:
|
|
1680
|
+
post_data = request_obj.post_data
|
|
1681
|
+
except Exception:
|
|
1682
|
+
post_data = None
|
|
1683
|
+
log.info(
|
|
1684
|
+
"ui_automation.batch_request_body",
|
|
1685
|
+
url=request_obj.url,
|
|
1686
|
+
filter_project_id=project_id,
|
|
1687
|
+
summary=_summarize_batch_request_body(post_data),
|
|
1688
|
+
)
|
|
1689
|
+
|
|
1690
|
+
page.on("request", on_request)
|
|
1691
|
+
|
|
1692
|
+
_detached = False
|
|
1693
|
+
|
|
1694
|
+
def detach() -> None:
|
|
1695
|
+
nonlocal _detached
|
|
1696
|
+
if _detached:
|
|
1697
|
+
return
|
|
1698
|
+
_detached = True
|
|
1699
|
+
try:
|
|
1700
|
+
page.remove_listener("request", on_request)
|
|
1701
|
+
except Exception:
|
|
1702
|
+
pass
|
|
1703
|
+
|
|
1704
|
+
return detach
|
|
1705
|
+
|
|
1596
1706
|
@staticmethod
|
|
1597
1707
|
async def _await_captured(
|
|
1598
1708
|
captured: list[dict[str, Any]],
|
|
@@ -1814,6 +1924,18 @@ class UiAutomationTransport(VideoGenerationMixin):
|
|
|
1814
1924
|
if request.ref_paths:
|
|
1815
1925
|
await self._attach_references(page, list(request.ref_paths), out_dir=out_dir)
|
|
1816
1926
|
|
|
1927
|
+
# Entity references: attach locked CHARACTER entities via the Personagens
|
|
1928
|
+
# picker (inherited from the video transport). The entity must live in the
|
|
1929
|
+
# project we generate in (pass --project / project_id). Flow's JS then
|
|
1930
|
+
# includes them on the submit; the request logger below records whether the
|
|
1931
|
+
# outgoing batchGenerateImages carries `referenceEntities` (spike signal).
|
|
1932
|
+
if request.reference_entities:
|
|
1933
|
+
await self._attach_character_entities(
|
|
1934
|
+
page,
|
|
1935
|
+
zip_entity_refs(request.reference_entities, request.reference_entity_names),
|
|
1936
|
+
out_dir=out_dir,
|
|
1937
|
+
)
|
|
1938
|
+
|
|
1817
1939
|
# Attach the response listener SYNCHRONOUSLY before any prompt
|
|
1818
1940
|
# action. asyncio.create_task is unsafe here: it defers the listener
|
|
1819
1941
|
# registration until the new task gets event-loop scheduling, which
|
|
@@ -1821,6 +1943,9 @@ class UiAutomationTransport(VideoGenerationMixin):
|
|
|
1821
1943
|
# attach/await eliminates that race. Project-ID filter prevents stale
|
|
1822
1944
|
# responses from previously-visited projects accumulating in the list.
|
|
1823
1945
|
captured, detach = self._attach_batch_response_listener(page, project_id=nav_project_id)
|
|
1946
|
+
# Also log the OUTGOING request body summary so the entity-reference spike
|
|
1947
|
+
# can read whether the submit carries `referenceEntities`.
|
|
1948
|
+
req_log_detach = self._attach_batch_request_logger(page, project_id=nav_project_id)
|
|
1824
1949
|
# Record submit_time BEFORE the click so the post-submit-time filter
|
|
1825
1950
|
# in _await_captured can distinguish this prompt's responses from any
|
|
1826
1951
|
# stale entries that arrived between listener attach and the click.
|
|
@@ -1835,6 +1960,7 @@ class UiAutomationTransport(VideoGenerationMixin):
|
|
|
1835
1960
|
)
|
|
1836
1961
|
finally:
|
|
1837
1962
|
detach()
|
|
1963
|
+
req_log_detach()
|
|
1838
1964
|
|
|
1839
1965
|
# Collect images from ALL captured responses (Flow makes one API call
|
|
1840
1966
|
# per image when count > 1).
|
|
@@ -318,6 +318,22 @@ VIDEO_SUBMODE_SELECTORS: dict[str, tuple[str, ...]] = {
|
|
|
318
318
|
),
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
+
|
|
322
|
+
def zip_entity_refs(
|
|
323
|
+
entity_ids: tuple[str, ...],
|
|
324
|
+
entity_names: tuple[str, ...],
|
|
325
|
+
) -> list[tuple[str, str]]:
|
|
326
|
+
"""Pair character entity ids with display names for the Personagens picker.
|
|
327
|
+
|
|
328
|
+
Tiles are addressed by id (``data-tile-id="fe_id_<id>"``); the name is only a
|
|
329
|
+
human label for logs/error screenshots. When fewer names than ids are given,
|
|
330
|
+
the id stands in as its own name so the pairing never drops an entity. Shared
|
|
331
|
+
by the image (`ui_automation`) and video (R2V) entity-attach paths.
|
|
332
|
+
"""
|
|
333
|
+
names = list(entity_names)
|
|
334
|
+
return [(eid, names[i] if i < len(names) else eid) for i, eid in enumerate(entity_ids)]
|
|
335
|
+
|
|
336
|
+
|
|
321
337
|
# The editor SPA's ready anchor — the Slate prompt textbox. The /project/ URL
|
|
322
338
|
# nav fires before the UI mounts; this is the readiness gate (used by
|
|
323
339
|
# _wait_video_editor_ready and asserted in its test).
|
|
@@ -1585,14 +1601,9 @@ class VideoGenerationMixin:
|
|
|
1585
1601
|
)
|
|
1586
1602
|
elif request.mode is Mode.R2V:
|
|
1587
1603
|
if request.reference_entities:
|
|
1588
|
-
names = request.reference_entity_names or request.reference_entities
|
|
1589
|
-
entities = [
|
|
1590
|
-
(entity_id, names[i] if i < len(names) else entity_id)
|
|
1591
|
-
for i, entity_id in enumerate(request.reference_entities)
|
|
1592
|
-
]
|
|
1593
1604
|
await VideoGenerationMixin._attach_character_entities(
|
|
1594
1605
|
page,
|
|
1595
|
-
|
|
1606
|
+
zip_entity_refs(request.reference_entities, request.reference_entity_names),
|
|
1596
1607
|
out_dir=out_dir,
|
|
1597
1608
|
)
|
|
1598
1609
|
if request.reference_images:
|