gflow-cli 0.14.0__tar.gz → 0.15.1__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.1}/AGENTS.md +3 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/CHANGELOG.md +53 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/PKG-INFO +10 -10
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/README.md +8 -8
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/INDEX.md +6 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/PROJECT_STATUS.md +4 -2
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/USAGE.md +45 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/pyproject.toml +3 -3
- gflow_cli-0.15.1/scripts/diag/README.md +29 -0
- gflow_cli-0.14.0/scripts/diag_capture_flow_traffic.py → gflow_cli-0.15.1/scripts/diag/capture_flow_traffic.py +1 -1
- gflow_cli-0.15.1/scripts/diag/memory_profile.py +235 -0
- gflow_cli-0.14.0/scripts/diag_recaptcha_mint.py → gflow_cli-0.15.1/scripts/diag/recaptcha_mint.py +1 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/__init__.py +1 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/client.py +1 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/image.py +18 -2
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/ui_automation.py +127 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/ui_automation_video.py +26 -6
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_image.py +155 -13
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/recorder.py +6 -1
- gflow_cli-0.15.1/tests/api/test_client_launch_kwargs.py +77 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_image.py +58 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_ui_automation.py +166 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_ui_automation_video.py +26 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_image.py +289 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/dev/test_recording_client.py +4 -1
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_image_steps.py +1 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/uv.lock +25 -25
- gflow_cli-0.14.0/tests/api/test_client_launch_kwargs.py +0 -35
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/active.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/branch-review.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/changelog.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/check.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/doc-review.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/known-issues.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/next.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/plan.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/pr-council-review.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/predict.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/release.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/scenario.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.claude/commands/gflow/status.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.continue-here.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.env.template +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.gitattributes +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/CODEOWNERS +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/copilot-instructions.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/dependabot.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/workflows/ci.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/workflows/external-pr-triage.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/workflows/governance-advisory.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/workflows/governance-benchmark.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.github/workflows/release.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.gitignore +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.gitleaks.toml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.pre-commit-config.yaml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/.secrets.baseline +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/CLAUDE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/CONFIGURATION.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/CONTRIBUTING.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/DISCLAIMER.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/GEMINI.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/KNOWN_ISSUES.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/LICENSE +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/PLAN.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/PR162_MOVIE_CHARACTER_REVIEW.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/RELEASE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/ROADMAP.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/conftest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docker-compose.yml +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/AGENT_GUIDE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/ARCHITECTURE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/AUTHENTICATION.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/CHARACTER.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/CHARACTER_RECON.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/CONFIGURATION.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/DATA_LAYER.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/DEBUGGING.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/DEMOS.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/DEVELOPMENT.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/E2E_TESTING.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/EXTERNAL_STORAGE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/GITHUB.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/GOVERNANCE_BENCHMARK.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_data_layer.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_image_batch.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.10.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.11.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.12.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.13.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.7.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.8.1.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.9.0.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_v0.9.1.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/LIVE_VERIFICATION_video_download.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/MOVIE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/SECURITY.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/USER_GUIDE.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/assets/demo-split-pf.gif +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/assets/example-run.gif +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/schemas/movie-handoff.schema.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/2026-05-17-issue-15-handover.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/character-scenario.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/plans/2026-06-01-governance-enforcement-advisory/PLAN.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/plans/2026-06-04-character-create-recording.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/plans/2026-06-06-movie-p0-asyncio-hotfix.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/plans/2026-06-06-movie-p1-composition-manifest.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/plans/2026-06-06-movie-p2-native-identity-voice.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/specs/2026-06-06-movie-consistency-design.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/batch_from_config.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/multi_prompt_t2i.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/sample_config.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/sample_prompts.txt +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/single_image_t2i.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/examples/workflow_chain.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/llms.txt +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/01_upload_image.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/04_archive_workflow.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/05_createProject.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/06_batchGenerateImages.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/08_batchAsyncGenerateVideoStartAndEndImage.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/09_batchAsyncGenerateVideoReferenceImages.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/10_batchCheckAsyncVideoGenerationStatus_successful.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/11_batchCheckAsyncVideoGenerationStatus_failed.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/12_create_scene.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/13_sceneWorkflows_update.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/14_get_scene_workflows.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/samples/captured/15_commit_flowWorkflow.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/ci/check_doc_links.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/ci/check_materiality.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/ci/check_repo_hygiene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/debug_editor.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/debug_gen_settings.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/debug_settings.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/_recording_client.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/_spike_common.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/active_plan.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_i2v_frame_slots_dom.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_i2v_intercept_submit.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_i2v_model_select_repro.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_i2v_post_bind_state.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_image_add_media_dom.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/capture_locale_invariants.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/cdp_drive_and_probe.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/character_create_spike.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/character_create_spike_v2.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/dump_character_selectors.js +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/make_project.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/materiality_backtest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/monitor_pr_38.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/patch_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/record_flow_capture.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/skillopt/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/skillopt/harness.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/skillopt/tasks.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_char_editor_dom.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_char_gen_capture.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_movie_attach_payload.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_movie_entity_recon.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_movie_gen_capture.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_movie_picker_select.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_movie_voice_list.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/dev/spike_patch_entity.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/record_demo.ps1 +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/smoke_image.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/smoke_real_chrome_image.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/smoke_video_editor.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/smoke_worker_style.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/scripts/verify_chrome_auth_viability.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/README.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/gflow-cli/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/plan/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/pr-council-review/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/predict/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/scenario/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/skills/status/SKILL.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/sonar-project.properties +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/__main__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/_cli_helpers.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/_retry.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/_sapisidhash.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/dto.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/recaptcha.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/routes.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/scene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/_common.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/base.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/experimental/bearer.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/transports/experimental/sapisidhash.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/api/video.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/base.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/factory.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/internal_chromium.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/real_chrome.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/strategies.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/auth/verification.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/browser_manager.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/chain.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/chain_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_data.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_models.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_movie.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_run.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_scene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/cli_video.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/composition.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/config.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/chain_repo.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0001_initial.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0002_add_cloud_storage.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0003_add_scene_tables.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0004_add_scene_output_path.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0005_add_chain_links.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/0006_add_operations_metadata.sql +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/migrations/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/models.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/queries.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/redaction.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/repository.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/data/store.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/errors.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/exceptions.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/image_batch.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/json_output.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/media.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/movie_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/observability.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/paths.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/profile_store.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/services/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/services/character_create.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/src/gflow_cli/storage.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tasks/lessons.md +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/test_assets/sample_batch.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/test_assets/sample_batch.tsv +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/test_assets/sample_batch_invalid.tsv +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/fixtures/character_gen_response.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/fixtures/patch_entity_response.json +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_aisandbox_auth_error.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_aisandbox_auth_headers.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_bearer_redaction.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_delete_characters.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_generate_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_image.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_patch_entity.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_client_scene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_concurrency.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_dto.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_image_dto.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_post_json_aisandbox_auth.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_recaptcha.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_retry.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_routes.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_routes_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_routes_scene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_sapisidhash_helper.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_scene_models.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_video.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/test_video_request.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_base.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_bearer.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_common.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_evaluate_fetch.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_factory.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_fingerprint.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_sapisidhash.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_transport_timeout.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_ui_automation_batch.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_ui_automation_image_mode.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/api/transports/test_ui_character_editor.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/auth/strategies/test_factory.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/auth/strategies/test_strategies.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/auth/test_verification.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_auth_list.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_character_create.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_data.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_image_seed_removed.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_models.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_movie.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_run.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_scene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_video.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_cli_video_chain.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_error_handling.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_helpers.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_movie_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/cli/test_t2i_multi_prompt.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/composition/test_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/composition/test_compose_prompt.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/composition/test_handoff.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/conftest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_chain_repo.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_find_incomplete_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_models.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_packaging.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_recorder.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_recorder_character.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_redaction.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_repository.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_scene_persistence.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_settings_and_errors.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/data/test_store_migrations.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/dev/test_record_flow_capture.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/conftest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_aisandbox_auth_live.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_auth_verification_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_chain_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_character_create_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_data_layer_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_i2v_flags_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_image_batch_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_image_i2i_ref_cap_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_json_output_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_locale_selectors_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_scene_compose_live.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_transports_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_video_r2v_ref_cap_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/e2e/test_video_t2v_e2e.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/auth.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/auth_login.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/character_create.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/character_read.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/conftest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/image.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_auth_login_steps.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_auth_steps.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_character_create_steps.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_character_read_steps.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_step_collision_guard.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/test_video_chain_steps.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/features/video_chain.feature +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/fixtures/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/fixtures/seeded_catalog.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/image_batch/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/image_batch/test_image_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/image_batch/test_observability_events.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/integration/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/integration/conftest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/integration/constants.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/integration/test_storage_gcs.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/integration/test_storage_s3.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/scripts/test_capture_locale_invariants.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/scripts/test_check_materiality.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/scripts/test_check_repo_hygiene.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/scripts/test_materiality_backtest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/services/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/services/test_character_create_redaction.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/services/test_character_create_saga.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/services/test_character_gen_no_direct_post.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/smoke/__init__.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/smoke/test_profile_account_smoke.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/smoke/test_real_flow.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_auth.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_browser_manager.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_chain.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_chain_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_cli_data.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_config.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_conftest_isolation.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_data_queries.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_documentation_gate.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_errors.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_errors_403.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_json_output.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_manifest.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_marker_registry.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_media.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_observability.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_paths.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_profile_store.py +0 -0
- {gflow_cli-0.14.0 → gflow_cli-0.15.1}/tests/test_smoke.py +0 -0
|
@@ -76,10 +76,12 @@ The `skills/` directory ships installable agent skill docs in plain Markdown wit
|
|
|
76
76
|
| `gflow-cli` | [`skills/gflow-cli/SKILL.md`](skills/gflow-cli/SKILL.md) | User wants to run any `gflow` command — auth, T2V, I2V, T2I, I2I, batch |
|
|
77
77
|
| `predict` | [`skills/predict/SKILL.md`](skills/predict/SKILL.md) | Pre-implementation adversarial analysis before any high-stakes change |
|
|
78
78
|
| `scenario` | [`skills/scenario/SKILL.md`](skills/scenario/SKILL.md) | Edge-case explorer after a predict GO/CAUTION |
|
|
79
|
+
| `plan` | [`skills/plan/SKILL.md`](skills/plan/SKILL.md) | Create a structured task-by-task implementation plan for a feature |
|
|
80
|
+
| `status` | [`skills/status/SKILL.md`](skills/status/SKILL.md) | Show current plan state, progress, and next unchecked task |
|
|
79
81
|
| `pr-council-review` | [`skills/pr-council-review/SKILL.md`](skills/pr-council-review/SKILL.md) | Multi-dimensional PR council review |
|
|
80
82
|
|
|
81
83
|
**Cursor / Aider / Codex / Gemini CLI:** paste or include the relevant `SKILL.md` in your system context.
|
|
82
|
-
**Claude Code:**
|
|
84
|
+
**Claude Code:** the `/gflow:` slash commands in `.claude/commands/gflow/` are auto-discovered when the project is open — no extra setup needed. To register a skill globally, copy the command file to `~/.claude/commands/`.
|
|
83
85
|
**Custom agents:** fetch `skills/gflow-cli/SKILL.md` into your knowledge base before answering gflow questions.
|
|
84
86
|
|
|
85
87
|
The SkillOpt harness at `scripts/dev/skillopt/` measures how accurately each skill guides an agent, and supports multiple providers (Anthropic, OpenAI-compat, Gemini, local models). See [`scripts/dev/skillopt/README.md`](scripts/dev/skillopt/README.md).
|
|
@@ -7,6 +7,56 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.15.1] — 2026-06-10
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Added `--disable-dev-shm-usage` to Chrome launch args in both `FlowApiClient._persistent_context_kwargs()` and `UiAutomationTransport.setup()` — prevents OOM in Docker containers with the default 64 MB `/dev/shm` allocation; no effect on developer machines with adequate shared memory
|
|
15
|
+
- README Stats badges hardened against shields.io outages — GitHub-stat badges now pass `cacheSeconds=3600` (mitigates shields.io's shared GitHub token-pool exhaustion, the "Unable to select next GitHub token from pool" error) and the PyPI downloads badge moved from `img.shields.io/pypi/dm` to pepy.tech (pypistats rate-limits shields.io upstream)
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- `scripts/diag/` directory — documented home for investigation scripts that require a live authenticated profile; includes `memory_profile.py` (Chrome process-tree RSS profiler for issue #155), `capture_flow_traffic.py`, and `recaptcha_mint.py` (both moved from `scripts/` root via git mv, history preserved)
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Video status poll now raises `AuthExpiredError` (exit 3) immediately on HTTP 401 from `batchCheckAsyncVideoGenerationStatus` instead of silently timing out after 600 s with a bare `TimeoutError` (exit 1) — session expiry is now detected mid-workflow, not only at login time (issue #156)
|
|
24
|
+
|
|
25
|
+
## [0.15.0] — 2026-06-09
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **`gflow image` can reference locked CHARACTER entities** for character-consistent
|
|
30
|
+
stills. New `--reference-entity <id>` (repeatable) + `--reference-entity-name` on
|
|
31
|
+
`image t2i` / `i2i`, plus `--project <id>` to generate in an EXISTING project (where
|
|
32
|
+
the entities live) instead of a throwaway scratch project. Entities attach through
|
|
33
|
+
the editor's **Personagens picker** and ride the submit as `referenceEntities`
|
|
34
|
+
(confirmed against the live API); `_build_batch_generate_images_body` serializes them
|
|
35
|
+
so non-UI/headless transports get parity too. Entities count toward the per-model
|
|
36
|
+
reference cap. `--project` / `--reference-entity` are single-prompt only; for a pure
|
|
37
|
+
character reference use `t2i` (`i2i` still needs a `--ref`). See `docs/USAGE.md` →
|
|
38
|
+
"Character-consistent images (entity references)".
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- `--project` no longer overwrites an existing project's stored title/source in the
|
|
43
|
+
local history DB (the recorder preserves the curated title for non-created projects).
|
|
44
|
+
|
|
45
|
+
### Security
|
|
46
|
+
|
|
47
|
+
- `--project` / `--reference-entity` ids are validated at the CLI boundary
|
|
48
|
+
(`[A-Za-z0-9-]{1,128}`), closing an unvalidated `page.goto` navigation path
|
|
49
|
+
(`project_editor_url` lacked the allowlist its sibling routes enforce) and a
|
|
50
|
+
CSS-selector injection vector (`data-tile-id='fe_id_<id>'`). The request-body debug
|
|
51
|
+
logger elides large reference-field values so Flow-built image bytes can't leak into
|
|
52
|
+
logs.
|
|
53
|
+
|
|
54
|
+
### Internal
|
|
55
|
+
|
|
56
|
+
- Bump dev/CI `ruff` to `0.15.16` (both the `dev` extra and the `dependency-groups`
|
|
57
|
+
pin; supersedes Dependabot PR #165, which updated only the soft `>=` extra and not
|
|
58
|
+
the hard `==` group pin CI actually uses). `ruff check` / `format --check` clean.
|
|
59
|
+
|
|
10
60
|
## [0.14.0] — 2026-06-07
|
|
11
61
|
|
|
12
62
|
### Added
|
|
@@ -1434,7 +1484,9 @@ shell-script template that branches on these codes.
|
|
|
1434
1484
|
|
|
1435
1485
|
First skeleton. Not functional end-to-end yet.
|
|
1436
1486
|
|
|
1437
|
-
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.
|
|
1487
|
+
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.15.1...HEAD
|
|
1488
|
+
[0.15.1]: https://github.com/ffroliva/gflow-cli/compare/v0.15.0...v0.15.1
|
|
1489
|
+
[0.15.0]: https://github.com/ffroliva/gflow-cli/compare/v0.14.0...v0.15.0
|
|
1438
1490
|
[0.14.0]: https://github.com/ffroliva/gflow-cli/compare/v0.13.0...v0.14.0
|
|
1439
1491
|
[0.13.0]: https://github.com/ffroliva/gflow-cli/compare/v0.12.0...v0.13.0
|
|
1440
1492
|
[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.1
|
|
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'
|
|
@@ -196,13 +196,13 @@ gflow CLI → Provider (interchangeable) → Flow (ui_automation) / Mock (te
|
|
|
196
196
|
|
|
197
197
|
## Stats
|
|
198
198
|
|
|
199
|
-
[](https://github.com/ffroliva/gflow-cli/stargazers)
|
|
200
|
-
[](https://github.com/ffroliva/gflow-cli/network/members)
|
|
201
|
-
[](https://github.com/ffroliva/gflow-cli/watchers)
|
|
202
|
-
[](https://github.com/ffroliva/gflow-cli/issues)
|
|
203
|
-
[](https://github.com/ffroliva/gflow-cli/pulls)
|
|
204
|
-
[](https://github.com/ffroliva/gflow-cli/commits/main)
|
|
205
|
-
[](https://github.com/ffroliva/gflow-cli)
|
|
206
|
-
[](https://github.com/ffroliva/gflow-cli/stargazers)
|
|
200
|
+
[](https://github.com/ffroliva/gflow-cli/network/members)
|
|
201
|
+
[](https://github.com/ffroliva/gflow-cli/watchers)
|
|
202
|
+
[](https://github.com/ffroliva/gflow-cli/issues)
|
|
203
|
+
[](https://github.com/ffroliva/gflow-cli/pulls)
|
|
204
|
+
[](https://github.com/ffroliva/gflow-cli/commits/main)
|
|
205
|
+
[](https://github.com/ffroliva/gflow-cli)
|
|
206
|
+
[](https://pepy.tech/project/gflow-cli)
|
|
207
207
|
|
|
208
208
|
If `gflow-cli` saves you time, please ⭐ the repo — it is the cheapest way to support the project.
|
|
@@ -132,13 +132,13 @@ gflow CLI → Provider (interchangeable) → Flow (ui_automation) / Mock (te
|
|
|
132
132
|
|
|
133
133
|
## Stats
|
|
134
134
|
|
|
135
|
-
[](https://github.com/ffroliva/gflow-cli/stargazers)
|
|
136
|
-
[](https://github.com/ffroliva/gflow-cli/network/members)
|
|
137
|
-
[](https://github.com/ffroliva/gflow-cli/watchers)
|
|
138
|
-
[](https://github.com/ffroliva/gflow-cli/issues)
|
|
139
|
-
[](https://github.com/ffroliva/gflow-cli/pulls)
|
|
140
|
-
[](https://github.com/ffroliva/gflow-cli/commits/main)
|
|
141
|
-
[](https://github.com/ffroliva/gflow-cli)
|
|
142
|
-
[](https://github.com/ffroliva/gflow-cli/stargazers)
|
|
136
|
+
[](https://github.com/ffroliva/gflow-cli/network/members)
|
|
137
|
+
[](https://github.com/ffroliva/gflow-cli/watchers)
|
|
138
|
+
[](https://github.com/ffroliva/gflow-cli/issues)
|
|
139
|
+
[](https://github.com/ffroliva/gflow-cli/pulls)
|
|
140
|
+
[](https://github.com/ffroliva/gflow-cli/commits/main)
|
|
141
|
+
[](https://github.com/ffroliva/gflow-cli)
|
|
142
|
+
[](https://pepy.tech/project/gflow-cli)
|
|
143
143
|
|
|
144
144
|
If `gflow-cli` saves you time, please ⭐ the repo — it is the cheapest way to support the project.
|
|
@@ -37,6 +37,7 @@ Welcome to the `gflow-cli` documentation. This index is the routing layer: it te
|
|
|
37
37
|
| **[tasks/lessons.md](../tasks/lessons.md)** | Running notebook of patterns + reviewer findings, dated and traced to commits | Starting a new phase; debugging "why did the council flag this?" |
|
|
38
38
|
| **[skills/README.md](../skills/README.md)** | Installable agent skill docs (gflow-cli, predict, pr-council-review, scenario) — cross-tool portable Markdown consumed by Claude Code, Cursor, Codex, Gemini CLI, Aider, etc. | Any agent wanting to use gflow-cli correctly |
|
|
39
39
|
| **[scripts/dev/skillopt/README.md](../scripts/dev/skillopt/README.md)** | SkillOpt mock harness — rollout→score loop for measuring and improving skill doc accuracy across multiple LLM providers | Measuring a skill edit's impact; comparing Claude vs GPT-4o vs Gemini on gflow tasks |
|
|
40
|
+
| **[scripts/diag/README.md](../scripts/diag/README.md)** | Diagnostic investigation scripts — run against a live authenticated profile to capture wire samples, measure Chrome memory, or mint reCAPTCHA tokens | Running a one-off investigation against a live Flow session; establishing baseline measurements for issue #155 |
|
|
40
41
|
|
|
41
42
|
## Agent commands
|
|
42
43
|
|
|
@@ -54,6 +55,9 @@ Slash commands for Claude Code, stored in `.claude/commands/gflow/`. All prefixe
|
|
|
54
55
|
| `/gflow:release` | Full release flow (calls `/gflow:changelog` + `/gflow:check`) | Cutting a new version |
|
|
55
56
|
| `/gflow:predict <proposal>` | 5-persona pre-implementation analysis → GO / CAUTION / STOP | Before any high-stakes design decision (new transport, auth change, selector redesign, schema migration) |
|
|
56
57
|
| `/gflow:scenario <feature>` | 12-dimension edge-case explorer → severity-ranked scenario table + BDD skeleton | After predict GO/CAUTION; before `/gflow:plan` |
|
|
58
|
+
| `/gflow:pr-council-review [PR#]` | Multi-dimensional council review of an open PR (5 baseline + adaptive dimensions) | Before merging any non-trivial PR; mandatory for auth/transport/data changes |
|
|
59
|
+
| `/gflow:branch-review` | Same council review run against the current local feature branch (no PR needed) | Pre-PR self-audit; after predict/scenario on a high-stakes branch |
|
|
60
|
+
| `/gflow:doc-review` | Systematic council-driven audit of documentation completeness and drift | Before cutting a release; after major documentation changes |
|
|
57
61
|
|
|
58
62
|
**Governance:** commands are executable docs — they decay like any doc. When a phase advances or a file path changes, update the relevant command in the same commit. `/gflow:release` includes a staleness review step.
|
|
59
63
|
|
|
@@ -90,6 +94,7 @@ Slash commands for Claude Code, stored in `.claude/commands/gflow/`. All prefixe
|
|
|
90
94
|
**"How do I use this project's skills in Cursor / Codex / Gemini CLI / Aider?"** → [skills/README.md](../skills/README.md#use-with-other-agents)
|
|
91
95
|
**"How do I benchmark a skill doc against real tasks?"** → [scripts/dev/skillopt/README.md](../scripts/dev/skillopt/README.md)
|
|
92
96
|
**"How do I compare Claude vs GPT-4o vs Gemini on gflow tasks?"** → `python scripts/dev/skillopt/harness.py --provider openai --model gpt-4o` (see [skillopt README](../scripts/dev/skillopt/README.md))
|
|
97
|
+
**"What does Chrome actually use in RAM during a generation?"** → run `uv run python scripts/diag/memory_profile.py --profile NAME` (see [scripts/diag/README.md](../scripts/diag/README.md))
|
|
93
98
|
**"How do I report a security issue?"** → [SECURITY § Reporting](SECURITY.md#reporting)
|
|
94
99
|
**"What branch do I work on? How do I name it?"** → [DEVELOPMENT § Branching model](DEVELOPMENT.md#branching-model)
|
|
95
100
|
**"How do I handle an external GitHub PR?"** → [GITHUB § Scenario Matrix](GITHUB.md#scenario-matrix)
|
|
@@ -104,7 +109,7 @@ Slash commands for Claude Code, stored in `.claude/commands/gflow/`. All prefixe
|
|
|
104
109
|
**"A gflow command hangs / fails — where do I start?"** → [DEBUGGING § Quick reference](DEBUGGING.md#quick-reference)
|
|
105
110
|
**"Flow's UI broke a selector — how do I diagnose it?"** → [DEBUGGING § Inspecting Flow's live UI](DEBUGGING.md#inspecting-flows-live-ui)
|
|
106
111
|
**"What does each `ui_automation.*` log event mean?"** → [DEBUGGING § Listener & HTTP-layer debugging](DEBUGGING.md#listener--http-layer-debugging)
|
|
107
|
-
**"What was actually live-verified for the latest release?"** → [LIVE_VERIFICATION_v0.13.0](LIVE_VERIFICATION_v0.13.0.md) · prior: [v0.12.0](LIVE_VERIFICATION_v0.12.0.md) · [v0.11.0](LIVE_VERIFICATION_v0.11.0.md) · [v0.10.0](LIVE_VERIFICATION_v0.10.0.md) · [v0.9.1](LIVE_VERIFICATION_v0.9.1.md)
|
|
112
|
+
**"What was actually live-verified for the latest release?"** → v0.15.0 / v0.14.x: no dedicated live-verification doc (CI + the v0.13.0 baseline). Latest doc: [LIVE_VERIFICATION_v0.13.0](LIVE_VERIFICATION_v0.13.0.md) · prior: [v0.12.0](LIVE_VERIFICATION_v0.12.0.md) · [v0.11.0](LIVE_VERIFICATION_v0.11.0.md) · [v0.10.0](LIVE_VERIFICATION_v0.10.0.md) · [v0.9.1](LIVE_VERIFICATION_v0.9.1.md)
|
|
108
113
|
**"What was live-verified for the data layer (PR #58)?"** → [LIVE_VERIFICATION_data_layer](LIVE_VERIFICATION_data_layer.md) — 1 Imagen + 1 Veo credit on denon82, 6-layer ledger (file + magic + Pillow + DB rows + CLI round-trip + structlog)
|
|
109
114
|
**"What was live-verified for the video-download feature (#29)?"** → [LIVE_VERIFICATION_video_download](LIVE_VERIFICATION_video_download.md)
|
|
110
115
|
**"What is the jitter matrix evidence for `gflow image batch`?"** → [`LIVE_VERIFICATION_image_batch.md`](LIVE_VERIFICATION_image_batch.md) — jitter matrix evidence for `gflow image batch` (always-same-project mode)
|
|
@@ -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.1"
|
|
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
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# scripts/diag/ — Diagnostic Investigation Scripts
|
|
2
|
+
|
|
3
|
+
These scripts require a live authenticated Chrome profile to run. They are investigation tools — not CI gates and not developer workflow tools — that help answer "what does this system actually do?" questions by observing a real browser session. Each script produces human-readable or structured output and does not modify production state.
|
|
4
|
+
|
|
5
|
+
## Scripts
|
|
6
|
+
|
|
7
|
+
| Script | Purpose | Prerequisite | Run |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| `capture_flow_traffic.py` | Capture Flow's outgoing API requests via `page.route` | `gflow auth login` | `uv run python scripts/diag/capture_flow_traffic.py --profile NAME` |
|
|
10
|
+
| `recaptcha_mint.py` | What `site_key` + token does gflow-cli's `TokenMinter` produce? | `gflow auth login` (headed) | `uv run python scripts/diag/recaptcha_mint.py --profile NAME` |
|
|
11
|
+
| `memory_profile.py` | Chrome process-tree RSS at key milestones (issue #155) | `gflow auth login` + `pip install psutil` | `uv run python scripts/diag/memory_profile.py --profile NAME` |
|
|
12
|
+
|
|
13
|
+
## What belongs here
|
|
14
|
+
|
|
15
|
+
1. Requires a live authenticated session to run
|
|
16
|
+
2. Produces human-readable or structured output for investigation
|
|
17
|
+
3. Does not write to production data stores
|
|
18
|
+
4. Answers a specific "what does this system actually do?" question
|
|
19
|
+
|
|
20
|
+
## What does NOT belong here
|
|
21
|
+
|
|
22
|
+
- **CI gates** → `scripts/ci/` (run on every commit, no auth needed)
|
|
23
|
+
- **Developer workflow tools** → `scripts/dev/` (`active_plan.py`, `skillopt/`, etc.)
|
|
24
|
+
- **Live smoke tests** → `scripts/` root (`smoke_*.py` — full end-to-end generation runs)
|
|
25
|
+
|
|
26
|
+
## Platform notes
|
|
27
|
+
|
|
28
|
+
- `memory_profile.py` requires `psutil`: `uv add --dev psutil` (not a hard dep — detected at runtime)
|
|
29
|
+
- All scripts: `uv run python scripts/diag/<name>.py` (no global Python install needed)
|
|
@@ -4,7 +4,7 @@ Spec § 11 mentioned a captured wire sample (samples/captured/06_batchGenerateIm
|
|
|
4
4
|
but the file doesn't exist. This script produces that ground truth — what
|
|
5
5
|
headers does Flow's UI actually attach when it calls aisandbox-pa?
|
|
6
6
|
|
|
7
|
-
Run: `uv run python scripts/
|
|
7
|
+
Run: `uv run python scripts/diag/capture_flow_traffic.py --profile <your-profile>`
|
|
8
8
|
|
|
9
9
|
Output goes to `tmp/captured/flow_outgoing_<utc>.jsonl` by default. **NEVER write
|
|
10
10
|
captured traffic to `samples/captured/`** — those files contain live Bearer tokens
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""Diagnostic — Chrome process-tree RSS at key milestones (issue #155).
|
|
2
|
+
|
|
3
|
+
Measures how much memory the Chrome/Chromium process tree consumes at four
|
|
4
|
+
points during a real browser launch against a gflow-cli profile:
|
|
5
|
+
|
|
6
|
+
baseline — before Playwright starts (current Python process only)
|
|
7
|
+
post_launch — immediately after launch_persistent_context returns
|
|
8
|
+
post_navigation — after page.goto(FLOW_URL, wait_until="networkidle")
|
|
9
|
+
post_close — after context.close() and Playwright stop
|
|
10
|
+
|
|
11
|
+
The output table shows Own RSS (the profiler's Python process) and Tree RSS
|
|
12
|
+
(profiler + all Chrome child processes) so you can see exactly how much RAM
|
|
13
|
+
Chrome adds at each stage.
|
|
14
|
+
|
|
15
|
+
Run: `uv run python scripts/diag/memory_profile.py --profile NAME [--output-json PATH]`
|
|
16
|
+
|
|
17
|
+
Prerequisite: gflow auth login (plus psutil — install with: uv add --dev psutil)
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import argparse
|
|
23
|
+
import asyncio
|
|
24
|
+
import json
|
|
25
|
+
import os
|
|
26
|
+
import sys
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
import psutil
|
|
31
|
+
except ImportError:
|
|
32
|
+
print("psutil is required: uv add --dev psutil", file=sys.stderr)
|
|
33
|
+
sys.exit(2)
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
from gflow_cli.api.transports.ui_automation import FLOW_URL
|
|
37
|
+
except ImportError:
|
|
38
|
+
FLOW_URL = "https://labs.google/fx/tools/flow?hl=en"
|
|
39
|
+
|
|
40
|
+
from playwright.async_api import async_playwright
|
|
41
|
+
|
|
42
|
+
from gflow_cli.auth import profile_dir
|
|
43
|
+
from gflow_cli.browser_manager import channel_for_profile
|
|
44
|
+
from gflow_cli.config import get_settings
|
|
45
|
+
|
|
46
|
+
CHROME_ARGS = [
|
|
47
|
+
"--disable-blink-features=AutomationControlled",
|
|
48
|
+
"--disable-dev-shm-usage",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
_COL_MILESTONE = 16
|
|
52
|
+
_COL_OWN = 14
|
|
53
|
+
_COL_TREE = 15
|
|
54
|
+
_COL_DELTA = 12
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _tree_rss_mb(pid: int) -> float:
|
|
58
|
+
"""Return total RSS (MB) of a process and all its descendants."""
|
|
59
|
+
try:
|
|
60
|
+
proc = psutil.Process(pid)
|
|
61
|
+
procs = [proc, *proc.children(recursive=True)]
|
|
62
|
+
return sum(p.memory_info().rss for p in procs if p.is_running()) / (1024 * 1024)
|
|
63
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
64
|
+
return 0.0
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _own_rss_mb() -> float:
|
|
68
|
+
"""Return RSS (MB) of only the current Python process."""
|
|
69
|
+
try:
|
|
70
|
+
return psutil.Process(os.getpid()).memory_info().rss / (1024 * 1024)
|
|
71
|
+
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
72
|
+
return 0.0
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _print_table_header() -> None:
|
|
76
|
+
header = (
|
|
77
|
+
f"{'Milestone':<{_COL_MILESTONE}} | "
|
|
78
|
+
f"{'Own RSS (MB)':>{_COL_OWN}} | "
|
|
79
|
+
f"{'Tree RSS (MB)':>{_COL_TREE}} | "
|
|
80
|
+
f"{'Delta (MB)':>{_COL_DELTA}}"
|
|
81
|
+
)
|
|
82
|
+
sep = "-" * len(header)
|
|
83
|
+
print(sep)
|
|
84
|
+
print(header)
|
|
85
|
+
print(sep)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _print_table_row(name: str, own_mb: float, tree_mb: float, delta: float | None) -> None:
|
|
89
|
+
delta_str = "—" if delta is None else f"{delta:+.1f}"
|
|
90
|
+
print(
|
|
91
|
+
f"{name:<{_COL_MILESTONE}} | "
|
|
92
|
+
f"{own_mb:>{_COL_OWN}.1f} | "
|
|
93
|
+
f"{tree_mb:>{_COL_TREE}.1f} | "
|
|
94
|
+
f"{delta_str:>{_COL_DELTA}}"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
async def run(profile_name: str, output_json: Path | None) -> None:
|
|
99
|
+
"""Main diagnostic loop."""
|
|
100
|
+
# Resolve profile directory using GFLOW_CLI_HOME
|
|
101
|
+
settings = get_settings()
|
|
102
|
+
_ = settings.home # ensure settings loaded; profile_dir() uses get_settings() internally
|
|
103
|
+
pdir = profile_dir(profile_name)
|
|
104
|
+
if not pdir.exists():
|
|
105
|
+
print(f"ERROR: Profile directory not found: {pdir}", file=sys.stderr)
|
|
106
|
+
sys.exit(1)
|
|
107
|
+
|
|
108
|
+
milestones: list[dict[str, object]] = []
|
|
109
|
+
pid = os.getpid()
|
|
110
|
+
|
|
111
|
+
# -------------------------------------------------------------------------
|
|
112
|
+
# Milestone 1: baseline (before Playwright starts)
|
|
113
|
+
# -------------------------------------------------------------------------
|
|
114
|
+
own_baseline = _own_rss_mb()
|
|
115
|
+
tree_baseline = _tree_rss_mb(pid)
|
|
116
|
+
milestones.append(
|
|
117
|
+
{
|
|
118
|
+
"name": "baseline",
|
|
119
|
+
"own_rss_mb": round(own_baseline, 2),
|
|
120
|
+
"tree_rss_mb": round(tree_baseline, 2),
|
|
121
|
+
"delta_mb": None,
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
_print_table_header()
|
|
126
|
+
_print_table_row("baseline", own_baseline, tree_baseline, None)
|
|
127
|
+
|
|
128
|
+
channel = channel_for_profile(pdir)
|
|
129
|
+
|
|
130
|
+
async with async_playwright() as pw:
|
|
131
|
+
launcher = pw.chromium
|
|
132
|
+
|
|
133
|
+
# -------------------------------------------------------------------------
|
|
134
|
+
# Milestone 2: post_launch
|
|
135
|
+
# -------------------------------------------------------------------------
|
|
136
|
+
ctx = await launcher.launch_persistent_context(
|
|
137
|
+
str(pdir),
|
|
138
|
+
headless=False,
|
|
139
|
+
args=CHROME_ARGS,
|
|
140
|
+
locale="en-US",
|
|
141
|
+
**({"channel": channel} if channel else {}),
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
own_post_launch = _own_rss_mb()
|
|
145
|
+
tree_post_launch = _tree_rss_mb(pid)
|
|
146
|
+
delta_launch = tree_post_launch - tree_baseline
|
|
147
|
+
milestones.append(
|
|
148
|
+
{
|
|
149
|
+
"name": "post_launch",
|
|
150
|
+
"own_rss_mb": round(own_post_launch, 2),
|
|
151
|
+
"tree_rss_mb": round(tree_post_launch, 2),
|
|
152
|
+
"delta_mb": round(delta_launch, 2),
|
|
153
|
+
}
|
|
154
|
+
)
|
|
155
|
+
_print_table_row("post_launch", own_post_launch, tree_post_launch, delta_launch)
|
|
156
|
+
|
|
157
|
+
# -------------------------------------------------------------------------
|
|
158
|
+
# Milestone 3: post_navigation
|
|
159
|
+
# -------------------------------------------------------------------------
|
|
160
|
+
page = ctx.pages[0] if ctx.pages else await ctx.new_page()
|
|
161
|
+
print(f"Navigating to {FLOW_URL} ...")
|
|
162
|
+
try:
|
|
163
|
+
await page.goto(FLOW_URL, wait_until="networkidle", timeout=45_000)
|
|
164
|
+
except Exception as exc: # noqa: BLE001
|
|
165
|
+
print(f"WARNING: navigation did not fully settle: {exc}", file=sys.stderr)
|
|
166
|
+
|
|
167
|
+
own_post_nav = _own_rss_mb()
|
|
168
|
+
tree_post_nav = _tree_rss_mb(pid)
|
|
169
|
+
delta_nav = tree_post_nav - tree_baseline
|
|
170
|
+
milestones.append(
|
|
171
|
+
{
|
|
172
|
+
"name": "post_navigation",
|
|
173
|
+
"own_rss_mb": round(own_post_nav, 2),
|
|
174
|
+
"tree_rss_mb": round(tree_post_nav, 2),
|
|
175
|
+
"delta_mb": round(delta_nav, 2),
|
|
176
|
+
}
|
|
177
|
+
)
|
|
178
|
+
_print_table_row("post_navigation", own_post_nav, tree_post_nav, delta_nav)
|
|
179
|
+
|
|
180
|
+
# -------------------------------------------------------------------------
|
|
181
|
+
# Milestone 4: post_close
|
|
182
|
+
# -------------------------------------------------------------------------
|
|
183
|
+
await ctx.close()
|
|
184
|
+
|
|
185
|
+
own_post_close = _own_rss_mb()
|
|
186
|
+
tree_post_close = _tree_rss_mb(pid)
|
|
187
|
+
delta_close = tree_post_close - tree_baseline
|
|
188
|
+
milestones.append(
|
|
189
|
+
{
|
|
190
|
+
"name": "post_close",
|
|
191
|
+
"own_rss_mb": round(own_post_close, 2),
|
|
192
|
+
"tree_rss_mb": round(tree_post_close, 2),
|
|
193
|
+
"delta_mb": round(delta_close, 2),
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
_print_table_row("post_close", own_post_close, tree_post_close, delta_close)
|
|
197
|
+
print("-" * (_COL_MILESTONE + _COL_OWN + _COL_TREE + _COL_DELTA + 9))
|
|
198
|
+
|
|
199
|
+
# -------------------------------------------------------------------------
|
|
200
|
+
# JSON output (optional)
|
|
201
|
+
# -------------------------------------------------------------------------
|
|
202
|
+
if output_json is not None:
|
|
203
|
+
result = {
|
|
204
|
+
"platform": sys.platform,
|
|
205
|
+
"chrome_args": CHROME_ARGS,
|
|
206
|
+
"milestones": milestones,
|
|
207
|
+
}
|
|
208
|
+
output_json.parent.mkdir(parents=True, exist_ok=True)
|
|
209
|
+
output_json.write_text(json.dumps(result, indent=2), encoding="utf-8")
|
|
210
|
+
print(f"JSON written to: {output_json}")
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def main() -> None:
|
|
214
|
+
parser = argparse.ArgumentParser(
|
|
215
|
+
description=__doc__,
|
|
216
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
217
|
+
)
|
|
218
|
+
parser.add_argument(
|
|
219
|
+
"--profile",
|
|
220
|
+
required=True,
|
|
221
|
+
help="Name of the gflow-cli profile (directory under GFLOW_CLI_HOME)",
|
|
222
|
+
)
|
|
223
|
+
parser.add_argument(
|
|
224
|
+
"--output-json",
|
|
225
|
+
type=Path,
|
|
226
|
+
default=None,
|
|
227
|
+
metavar="PATH",
|
|
228
|
+
help="Optional path to write machine-readable results as JSON",
|
|
229
|
+
)
|
|
230
|
+
args = parser.parse_args()
|
|
231
|
+
asyncio.run(run(args.profile, args.output_json))
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
if __name__ == "__main__":
|
|
235
|
+
main()
|
gflow_cli-0.14.0/scripts/diag_recaptcha_mint.py → gflow_cli-0.15.1/scripts/diag/recaptcha_mint.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Diagnostic — what site_key + token does gflow-cli's TokenMinter produce?
|
|
2
2
|
|
|
3
|
-
Run: `uv run python scripts/
|
|
3
|
+
Run: `uv run python scripts/diag/recaptcha_mint.py --profile <your-profile>`
|
|
4
4
|
|
|
5
5
|
Opens HEADED Chromium, navigates to Flow, runs TokenMinter, prints the
|
|
6
6
|
discovered site_key + minted token length. Compare to HAR ground truth:
|
|
@@ -293,7 +293,7 @@ class FlowApiClient:
|
|
|
293
293
|
"--no-sandbox",
|
|
294
294
|
"--password-store=basic",
|
|
295
295
|
],
|
|
296
|
-
"args": ["--disable-blink-features=AutomationControlled"],
|
|
296
|
+
"args": ["--disable-blink-features=AutomationControlled", "--disable-dev-shm-usage"],
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
async def _enter_setup(self) -> None:
|