gflow-cli 0.4.0a2__tar.gz → 0.6.0a1__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.4.0a2 → gflow_cli-0.6.0a1}/.claude/commands/release.md +21 -10
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.gitattributes +4 -2
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.github/workflows/ci.yml +8 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.github/workflows/release.yml +5 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.gitignore +7 -0
- gflow_cli-0.6.0a1/.planning/todos/pending/2026-05-11-add-project-logo-and-docs-site-promotion-plan.md +38 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/CHANGELOG.md +133 -3
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/CLAUDE.md +63 -0
- gflow_cli-0.6.0a1/CONFIGURATION.md +68 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/PKG-INFO +44 -11
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/README.md +43 -10
- gflow_cli-0.6.0a1/RELEASE.md +97 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/AUTHENTICATION.md +1 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/INDEX.md +2 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/SECURITY.md +1 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/USAGE.md +97 -4
- gflow_cli-0.6.0a1/docs/assets/example-run.gif +0 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/2026-05-14-shell-multi-prompt-orchestration.md +165 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_CODE.md +46 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_GEMINI.md +89 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_SECURITY.md +70 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_PYTHON.md +37 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_SECURITY.md +33 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN.md +1919 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_CODE.md +70 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_FOLLOWUP.md +36 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_PLANNER.md +66 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY.md +70 -0
- gflow_cli-0.6.0a1/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY_FOLLOWUP.md +30 -0
- gflow_cli-0.6.0a1/docs/superpowers/specs/2026-05-14-shell-multi-prompt-design.md +497 -0
- gflow_cli-0.6.0a1/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +123 -0
- gflow_cli-0.6.0a1/examples/README.md +67 -0
- gflow_cli-0.6.0a1/examples/batch_from_config.py +99 -0
- gflow_cli-0.6.0a1/examples/multi_prompt_t2i.py +126 -0
- gflow_cli-0.6.0a1/examples/sample_config.json +18 -0
- gflow_cli-0.6.0a1/examples/sample_prompts.txt +4 -0
- gflow_cli-0.6.0a1/examples/single_image_t2i.py +135 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/pyproject.toml +5 -1
- gflow_cli-0.6.0a1/scripts/diag_capture_flow_traffic.py +125 -0
- gflow_cli-0.6.0a1/scripts/diag_recaptcha_mint.py +77 -0
- gflow_cli-0.6.0a1/scripts/record_demo.ps1 +226 -0
- gflow_cli-0.6.0a1/scripts/smoke_real_chrome_image.py +416 -0
- gflow_cli-0.6.0a1/scripts/smoke_worker_style.py +415 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/__init__.py +1 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/_cli_helpers.py +31 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/client.py +100 -57
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/image.py +13 -3
- gflow_cli-0.6.0a1/src/gflow_cli/api/transports/__init__.py +83 -0
- gflow_cli-0.6.0a1/src/gflow_cli/api/transports/_common.py +94 -0
- gflow_cli-0.6.0a1/src/gflow_cli/api/transports/_fingerprint.py +132 -0
- gflow_cli-0.6.0a1/src/gflow_cli/api/transports/base.py +60 -0
- gflow_cli-0.6.0a1/src/gflow_cli/api/transports/experimental/__init__.py +29 -0
- gflow_cli-0.6.0a1/src/gflow_cli/api/transports/experimental/bearer.py +334 -0
- gflow_cli-0.6.0a1/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +306 -0
- gflow_cli-0.6.0a1/src/gflow_cli/api/transports/experimental/sapisidhash.py +297 -0
- gflow_cli-0.6.0a1/src/gflow_cli/api/transports/ui_automation.py +611 -0
- gflow_cli-0.6.0a1/src/gflow_cli/browser_manager.py +633 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/cli.py +2 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/cli_image.py +241 -37
- gflow_cli-0.6.0a1/src/gflow_cli/cli_run.py +351 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/cli_video.py +2 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/config.py +12 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/errors.py +49 -0
- gflow_cli-0.6.0a1/src/gflow_cli/image_batch.py +360 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tasks/lessons.md +79 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_client.py +134 -0
- gflow_cli-0.6.0a1/tests/api/test_client_image.py +809 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_image.py +19 -10
- gflow_cli-0.6.0a1/tests/api/transports/test_base.py +42 -0
- gflow_cli-0.6.0a1/tests/api/transports/test_bearer.py +444 -0
- gflow_cli-0.6.0a1/tests/api/transports/test_common.py +206 -0
- gflow_cli-0.6.0a1/tests/api/transports/test_evaluate_fetch.py +462 -0
- gflow_cli-0.6.0a1/tests/api/transports/test_factory.py +60 -0
- gflow_cli-0.6.0a1/tests/api/transports/test_fingerprint.py +119 -0
- gflow_cli-0.6.0a1/tests/api/transports/test_sapisidhash.py +389 -0
- gflow_cli-0.6.0a1/tests/api/transports/test_ui_automation.py +996 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/cli/test_cli_image.py +119 -0
- gflow_cli-0.6.0a1/tests/cli/test_cli_run.py +421 -0
- gflow_cli-0.6.0a1/tests/cli/test_t2i_multi_prompt.py +410 -0
- gflow_cli-0.6.0a1/tests/e2e/__init__.py +0 -0
- gflow_cli-0.6.0a1/tests/e2e/test_transports_e2e.py +313 -0
- gflow_cli-0.6.0a1/tests/features/__init__.py +0 -0
- gflow_cli-0.6.0a1/tests/features/image.feature +56 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/test_image_steps.py +115 -1
- gflow_cli-0.6.0a1/tests/smoke/__init__.py +0 -0
- gflow_cli-0.6.0a1/tests/smoke/test_real_flow.py +88 -0
- gflow_cli-0.6.0a1/tests/test_browser_manager.py +1541 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_errors.py +28 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_smoke.py +1 -1
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/uv.lock +7 -1
- gflow_cli-0.4.0a2/tests/api/test_client_image.py +0 -799
- gflow_cli-0.4.0a2/tests/features/image.feature +0 -25
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.claude/README.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/.env.template +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/CONTRIBUTING.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/DISCLAIMER.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/KNOWN_ISSUES.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/LICENSE +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/PLAN.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/ARCHITECTURE.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/CONFIGURATION.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/USER_GUIDE.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/README.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/01_upload_image.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/04_archive_workflow.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/05_createProject.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/06_batchGenerateImages.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/scripts/smoke_e2e.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/scripts/smoke_image.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/skills/README.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/skills/gflow-cli/SKILL.md +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/__main__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/__init__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/_retry.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/dto.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/recaptcha.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/routes.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/api/video.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/auth.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/manifest.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/observability.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/paths.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/src/gflow_cli/profile_store.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/__init__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/__init__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_client_generate_video.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_concurrency.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_dto.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_image_dto.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_recaptcha.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_retry.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_routes.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/api/test_video.py +0 -0
- {gflow_cli-0.4.0a2/tests/cli → gflow_cli-0.6.0a1/tests/api/transports}/__init__.py +0 -0
- {gflow_cli-0.4.0a2/tests/features → gflow_cli-0.6.0a1/tests/cli}/__init__.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/cli/test_error_handling.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/cli/test_helpers.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/conftest.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/auth.feature +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/conftest.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/test_auth_steps.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/test_step_collision_guard.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/test_video_steps.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/features/video.feature +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_auth.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_cli_video.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_config.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_manifest.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_observability.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_paths.py +0 -0
- {gflow_cli-0.4.0a2 → gflow_cli-0.6.0a1}/tests/test_profile_store.py +0 -0
|
@@ -9,8 +9,8 @@ You are about to release a new version of `gflow-cli`. Follow this sequence verb
|
|
|
9
9
|
## Inputs
|
|
10
10
|
|
|
11
11
|
Ask the user (if not already provided):
|
|
12
|
-
1. **Version** — the new
|
|
13
|
-
2. **Pre-release?** — `0.
|
|
12
|
+
1. **Version** — the new version (e.g. `0.4.0`, `0.4.0a3`, `1.0.0rc1`). Use PEP 440 prerelease suffixes (`aN`, `bN`, `rcN`) for Python package releases. If they don't know, look at the latest entry in `CHANGELOG.md` `[Unreleased]` and propose the next bump (PATCH for fixes only, MINOR for new features, MAJOR for breaks).
|
|
13
|
+
2. **Pre-release?** — prerelease versions such as `0.4.0a3` should stay marked as GitHub prereleases. Only the user can say when a release line is ready for the stable tag, such as `0.4.0`.
|
|
14
14
|
|
|
15
15
|
## Sequence
|
|
16
16
|
|
|
@@ -41,7 +41,17 @@ Ask the user (if not already provided):
|
|
|
41
41
|
version = "<NEW_VERSION>"
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
5. **
|
|
44
|
+
5. **Bump package version** in `src/gflow_cli/__init__.py`:
|
|
45
|
+
```python
|
|
46
|
+
__version__ = "<NEW_VERSION>"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
6. **Update version assertion tests** if present:
|
|
50
|
+
```bash
|
|
51
|
+
rg -n "__version__|<OLD_VERSION>|version assertion" tests src pyproject.toml
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
7. **Update `CHANGELOG.md`:**
|
|
45
55
|
- Move all entries under `## [Unreleased]` to a new `## [<NEW_VERSION>] — YYYY-MM-DD` section.
|
|
46
56
|
- Leave `## [Unreleased]` empty.
|
|
47
57
|
- Update the link footer:
|
|
@@ -50,24 +60,24 @@ Ask the user (if not already provided):
|
|
|
50
60
|
[<NEW_VERSION>]: https://github.com/ffroliva/gflow-cli/releases/tag/v<NEW_VERSION>
|
|
51
61
|
```
|
|
52
62
|
|
|
53
|
-
|
|
63
|
+
8. **Commit the release prep.**
|
|
54
64
|
```bash
|
|
55
|
-
git add pyproject.toml CHANGELOG.md
|
|
56
|
-
git commit -m "release: v<NEW_VERSION>"
|
|
65
|
+
git add pyproject.toml src/gflow_cli/__init__.py CHANGELOG.md tests
|
|
66
|
+
git commit -m "chore(release): v<NEW_VERSION>"
|
|
57
67
|
```
|
|
58
68
|
|
|
59
|
-
|
|
69
|
+
9. **Tag.** PEP 440 prerelease tags include `aN` / `bN` / `rcN`:
|
|
60
70
|
```bash
|
|
61
71
|
git tag -a v<NEW_VERSION> -m "v<NEW_VERSION>"
|
|
62
72
|
```
|
|
63
73
|
|
|
64
|
-
|
|
74
|
+
10. **Push commit + tag.**
|
|
65
75
|
```bash
|
|
66
76
|
git push origin main
|
|
67
77
|
git push origin v<NEW_VERSION>
|
|
68
78
|
```
|
|
69
79
|
|
|
70
|
-
|
|
80
|
+
11. **Report.** Tell the user:
|
|
71
81
|
- The pushed tag triggers `.github/workflows/release.yml`.
|
|
72
82
|
- Watch <https://github.com/ffroliva/gflow-cli/actions> for the release workflow.
|
|
73
83
|
- On success: PyPI publish + GitHub Release with auto-generated notes.
|
|
@@ -82,5 +92,6 @@ Ask the user (if not already provided):
|
|
|
82
92
|
|
|
83
93
|
## See also
|
|
84
94
|
|
|
85
|
-
- [
|
|
95
|
+
- [RELEASE.md](../../RELEASE.md) — full release protocol, prerelease policy, and checklist
|
|
96
|
+
- [README § Releases](../../README.md#releases) — short release policy & cadence
|
|
86
97
|
- [PLAN § Phase 5](../../PLAN.md#phase-5--public-alpha-release-on-pypi) — first-release exit criteria
|
|
@@ -28,8 +28,10 @@ LICENSE text eol=lf
|
|
|
28
28
|
*.sh text eol=lf
|
|
29
29
|
*.bash text eol=lf
|
|
30
30
|
|
|
31
|
-
#
|
|
32
|
-
|
|
31
|
+
# PowerShell handles LF fine on both PS 5.1 and Core, so keep .ps1 as LF.
|
|
32
|
+
# cmd.exe has historical edge cases with multi-line batch files, so .bat/.cmd
|
|
33
|
+
# stay CRLF.
|
|
34
|
+
*.ps1 text eol=lf
|
|
33
35
|
*.bat text eol=crlf
|
|
34
36
|
*.cmd text eol=crlf
|
|
35
37
|
|
|
@@ -32,4 +32,11 @@ jobs:
|
|
|
32
32
|
run: uv run pyright src
|
|
33
33
|
|
|
34
34
|
- name: Test (smoke only)
|
|
35
|
-
|
|
35
|
+
# e2e tests (tests/e2e/) require a logged-in `denon82` Chromium profile
|
|
36
|
+
# and live Flow auth — never runnable in CI. They self-mark with
|
|
37
|
+
# `pytestmark = pytest.mark.e2e` (file-level) and are opt-in via
|
|
38
|
+
# `-m e2e` per their module docstring. `live` marker is reserved for
|
|
39
|
+
# `GFLOW_LIVE=1` tests that hit the real Flow API. Both are excluded
|
|
40
|
+
# from the default smoke run; `tests/smoke/test_real_flow.py` already
|
|
41
|
+
# self-skips via `pytest.mark.skipif(GFLOW_E2E != "1")`.
|
|
42
|
+
run: uv run pytest -q -m "not e2e and not live"
|
|
@@ -50,4 +50,8 @@ jobs:
|
|
|
50
50
|
with:
|
|
51
51
|
generate_release_notes: true
|
|
52
52
|
files: dist/*
|
|
53
|
-
|
|
53
|
+
# Pre-release detection covers both conventions:
|
|
54
|
+
# - semver suffixes: v1.2.3-alpha1, v1.2.3-rc1, v1.2.3-beta1 (any '-' qualifies)
|
|
55
|
+
# - PEP 440 suffixes: v1.2.3a1, v1.2.3b1, v1.2.3rc1 (any 'a' / 'b' / 'rc')
|
|
56
|
+
# Stable tags like v1.2.3 contain none of these substrings.
|
|
57
|
+
prerelease: ${{ contains(github.ref_name, '-') || contains(github.ref_name, 'a') || contains(github.ref_name, 'b') || contains(github.ref_name, 'rc') }}
|
|
@@ -48,6 +48,13 @@ tmp/
|
|
|
48
48
|
!tests/fixtures/**/*.png
|
|
49
49
|
samples/*.captured.json # sandbox-recorded API exchanges may contain PII
|
|
50
50
|
|
|
51
|
+
# Live Flow traffic captures — NEVER commit (contain real Bearer tokens / API keys).
|
|
52
|
+
# Diagnostic scripts MUST default-write here, NOT to samples/captured/.
|
|
53
|
+
# Sanitised reference samples (no secrets) can still live under samples/captured/.
|
|
54
|
+
tmp/captured/
|
|
55
|
+
samples/captured/flow_outgoing_*.jsonl
|
|
56
|
+
samples/captured/flow_outgoing_*.json
|
|
57
|
+
|
|
51
58
|
# Claude Code worktrees and lock files
|
|
52
59
|
.claude/worktrees/
|
|
53
60
|
.claude/scheduled_tasks.lock
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
created: 2026-05-11T11:34:56.295Z
|
|
3
|
+
title: Add project logo and docs site promotion plan
|
|
4
|
+
area: docs
|
|
5
|
+
files:
|
|
6
|
+
- README.md:18
|
|
7
|
+
- README.md:365
|
|
8
|
+
- RELEASE.md:1
|
|
9
|
+
- docs/INDEX.md:10
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Problem
|
|
13
|
+
|
|
14
|
+
The project is now public on GitHub and PyPI and has enough release/process
|
|
15
|
+
surface to benefit from a more polished presentation. The README was cleaned up
|
|
16
|
+
with working badges and a public `RELEASE.md`, but the next promotion step is
|
|
17
|
+
still undecided: whether to add a logo/social preview, whether to create a
|
|
18
|
+
GitHub Pages documentation site, and which static-docs stack to use.
|
|
19
|
+
|
|
20
|
+
Jekyll is available on GitHub Pages, but for this Python CLI project the better
|
|
21
|
+
default is likely MkDocs Material: it fits Markdown-heavy CLI docs, has search
|
|
22
|
+
and navigation, and can publish to GitHub Pages cleanly. This should wait until
|
|
23
|
+
after the current prerelease E2E validation, because the real launch gate is
|
|
24
|
+
runtime confidence, not site polish.
|
|
25
|
+
|
|
26
|
+
## Solution
|
|
27
|
+
|
|
28
|
+
After E2E validation, decide a small promotion package:
|
|
29
|
+
|
|
30
|
+
1. Add a simple project logo and GitHub social preview image.
|
|
31
|
+
2. Keep README as the landing page and make the first screen clear for users.
|
|
32
|
+
3. If docs navigation grows cramped, add a MkDocs Material site published to
|
|
33
|
+
GitHub Pages.
|
|
34
|
+
4. Avoid Jekyll unless the goal shifts toward a blog-style marketing site.
|
|
35
|
+
5. Add the star-history chart only after the repo has enough activity for the
|
|
36
|
+
graph to render as useful signal rather than empty axes.
|
|
37
|
+
6. Keep `RELEASE.md`, README release policy, and `.claude/commands/release.md`
|
|
38
|
+
in sync when the release process changes.
|
|
@@ -7,6 +7,136 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.6.0a1] — 2026-05-14
|
|
11
|
+
|
|
12
|
+
> **Shell-friendly multi-prompt `t2i` + performance hardening.** This release
|
|
13
|
+
> promotes `gflow image t2i` to a variadic command that can consume multiple
|
|
14
|
+
> prompts from positional arguments, a line-delimited text file, or standard
|
|
15
|
+
> input. Core generation logic has been consolidated into a shared
|
|
16
|
+
> `image_batch` module, ensuring architectural consistency between shell runs
|
|
17
|
+
> and JSON-described batches. This version also ships critical resource
|
|
18
|
+
> cleanup fixes for SQLite connections and OOM protection for stdin streams.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **Variadic `gflow image t2i`** — now accepts multiple positional prompts.
|
|
23
|
+
Example: `gflow image t2i "prompt 1" "prompt 2"`.
|
|
24
|
+
- **`--prompts-file <PATH>` and `--stdin`** — read batches of prompts from
|
|
25
|
+
text files or pipes. All prompts in a batch share a single Flow session
|
|
26
|
+
and project, significantly reducing reCAPTCHA and project-init overhead.
|
|
27
|
+
- **Shared `image_batch` logic** (`src/gflow_cli/image_batch.py`) — unified
|
|
28
|
+
orchestration, validation, and rendering for all multi-prompt generation
|
|
29
|
+
surfaces.
|
|
30
|
+
- **Memory safety for stdin** — bounded read on standard input prevents
|
|
31
|
+
memory exhaustion when piping large or infinite streams.
|
|
32
|
+
- **`examples/multi_prompt_t2i.py` + `examples/sample_prompts.txt`** —
|
|
33
|
+
runnable template for the new shell-multi-prompt surface.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- **Resource leaks in SQLite** — ensured all `sqlite3` connections are
|
|
38
|
+
properly closed via `try...finally` blocks, resolving resource exhaust
|
|
39
|
+
warnings and potential hangs in long-running processes.
|
|
40
|
+
- **Output directory partitioning** — `t2i` batches now correctly land in
|
|
41
|
+
date-partitioned folders (`images/YYYY-MM-DD/`) by default, aligning
|
|
42
|
+
with the core design spec.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- **CLI validation alignment** — `t2i` and `i2i` subcommands now use
|
|
47
|
+
authoritative domain constants for model, aspect, and count validation,
|
|
48
|
+
ensuring UI help text and defaults stay in perfect sync with the engine.
|
|
49
|
+
|
|
50
|
+
## [0.5.0a1] — 2026-05-12
|
|
51
|
+
|
|
52
|
+
> **Pluggable image transport + JSON-described batch runs.** The image
|
|
53
|
+
> generation surface now ships a new default `ui_automation` transport —
|
|
54
|
+
> a Playwright-driven UI mimicry strategy validated end-to-end against
|
|
55
|
+
> real Flow on a Google AI Pro/Ultra profile. Three earlier HTTP
|
|
56
|
+
> transport strategies (`evaluate_fetch`, `bearer`, `sapisidhash`) move
|
|
57
|
+
> into a new `experimental/` subpackage; they remain importable for
|
|
58
|
+
> research but are hidden from the CLI by default. New top-level
|
|
59
|
+
> `gflow run --config <file>` command drives JSON-described sequential
|
|
60
|
+
> batches through one shared session.
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- **`UiAutomationTransport`** (`gflow_cli.api.transports.ui_automation`)
|
|
65
|
+
— new default transport. Drives the Flow editor on a logged-in
|
|
66
|
+
profile through a Playwright-managed persistent context (internal CDP
|
|
67
|
+
port; no externally-exposed debug port). Mirrors the validated
|
|
68
|
+
reference flow in `scripts/smoke_worker_style.py`.
|
|
69
|
+
- **`gflow run --config <file>`** — sequential JSON-described batch
|
|
70
|
+
command. Schema covers `profile`, `transport`, `output_dir`, and a
|
|
71
|
+
`prompts` list (1–50 entries) with per-prompt `text`,
|
|
72
|
+
`aspect_ratio`, `model`, `count`, and `output_filename`. Supports
|
|
73
|
+
`--continue-on-error` (default) and `--fail-fast` semantics; final
|
|
74
|
+
exit code is the max per-prompt exit code. ONE `FlowApiClient`
|
|
75
|
+
session wraps the whole loop so the browser/project persist across
|
|
76
|
+
prompts.
|
|
77
|
+
- **`examples/` directory** — three runnable scripts (`single_image_t2i.py`,
|
|
78
|
+
`batch_from_config.py`) + a copy-and-edit `sample_config.json` + an
|
|
79
|
+
index `examples/README.md`. All sanitised: no hardcoded profile
|
|
80
|
+
names, generic placeholder prompts, parameterised via `--profile` /
|
|
81
|
+
`$GFLOW_EXAMPLE_PROFILE`.
|
|
82
|
+
- **Opt-in real-Flow smoke test** at `tests/smoke/test_real_flow.py`,
|
|
83
|
+
gated by `GFLOW_E2E=1` + `GFLOW_E2E_PROFILE`. Runs the full
|
|
84
|
+
`UiAutomationTransport` flow against real Flow and asserts a
|
|
85
|
+
non-trivial PNG was written.
|
|
86
|
+
- **`EXPERIMENTAL_TRANSPORTS` constant** + **`transport_choices()`
|
|
87
|
+
helper** in `gflow_cli.api.transports`. The factory continues to
|
|
88
|
+
accept every registered key; the CLI `--transport` Choice list is
|
|
89
|
+
the gated surface (default = `ui_automation` only;
|
|
90
|
+
`GFLOW_CLI_EXPERIMENTAL_TRANSPORTS=1` expands to all four).
|
|
91
|
+
- **Download host allow-list** in `UiAutomationTransport._download`
|
|
92
|
+
(`googleusercontent.com`, `googleapis.com`, `google.com` suffix
|
|
93
|
+
match). `follow_redirects=False`. Prevents session cookies from
|
|
94
|
+
reaching a non-Google host through a malformed or compromised
|
|
95
|
+
`fifeUrl`.
|
|
96
|
+
|
|
97
|
+
### Changed
|
|
98
|
+
|
|
99
|
+
- **Default `--transport` flag** flipped from `evaluate_fetch` to
|
|
100
|
+
`ui_automation` across `gflow image t2i`, `gflow image i2i`, and
|
|
101
|
+
`gflow image upload`. The change is transparent to existing scripts
|
|
102
|
+
unless they pinned `--transport evaluate_fetch` explicitly.
|
|
103
|
+
- **`evaluate_fetch` / `bearer` / `sapisidhash` strategies moved** to
|
|
104
|
+
`gflow_cli.api.transports.experimental.*`. Public registry keys
|
|
105
|
+
(the strings used by `make_transport()` and the
|
|
106
|
+
`GFLOW_CLI_TRANSPORT` env var) are unchanged. Import paths within
|
|
107
|
+
the package are the only user-visible delta.
|
|
108
|
+
- **Debug screenshots** captured by the strategy on `_enter_editor` /
|
|
109
|
+
`_send_prompt` failures are now **viewport-only**
|
|
110
|
+
(`full_page=False`) and emit a `WARNING` log line noting the file
|
|
111
|
+
may contain identifying information from the authenticated session.
|
|
112
|
+
|
|
113
|
+
### Fixed
|
|
114
|
+
|
|
115
|
+
- Listener-attach race in `generate_images`. The earlier
|
|
116
|
+
`asyncio.create_task(_capture_batch_response(page))` scheduled the
|
|
117
|
+
listener registration AFTER the next event-loop tick; on a busy
|
|
118
|
+
loop the prompt click could fire before the listener attached,
|
|
119
|
+
causing the capture to time out. Refactored into a synchronous
|
|
120
|
+
`_attach_batch_response_listener(page)` + an `async
|
|
121
|
+
_await_captured(captured, ...)`. No more orphaned task on partial
|
|
122
|
+
failure.
|
|
123
|
+
|
|
124
|
+
### Removed
|
|
125
|
+
|
|
126
|
+
- Dead `_extract_image_urls(response)` helper on
|
|
127
|
+
`UiAutomationTransport` and its five tests.
|
|
128
|
+
`generate_images` parses `body.media[]` directly through
|
|
129
|
+
`GeneratedImage.from_response_item`; the parallel helper was
|
|
130
|
+
unreachable.
|
|
131
|
+
|
|
132
|
+
### Documentation
|
|
133
|
+
|
|
134
|
+
- `BrowserManager` module docstring updated to make explicit that the
|
|
135
|
+
module is retained for research / non-Flow use, not on the
|
|
136
|
+
v0.5.0a1 image-generation critical path. No behavior change.
|
|
137
|
+
- README "Project status" table updated with v0.5.0a1 row.
|
|
138
|
+
- `docs/USAGE.md` gains a `gflow run` section.
|
|
139
|
+
|
|
10
140
|
## [0.4.0a2] — 2026-05-11
|
|
11
141
|
|
|
12
142
|
> **Documentation polish.** Same release surface as v0.4.0a1; this tag fixes
|
|
@@ -307,9 +437,9 @@ shell-script template that branches on these codes.
|
|
|
307
437
|
|
|
308
438
|
First skeleton. Not functional end-to-end yet.
|
|
309
439
|
|
|
310
|
-
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.
|
|
311
|
-
[0.
|
|
312
|
-
[0.
|
|
440
|
+
[Unreleased]: https://github.com/ffroliva/gflow-cli/compare/v0.6.0a1...HEAD
|
|
441
|
+
[0.6.0a1]: https://github.com/ffroliva/gflow-cli/compare/v0.5.0a1...v0.6.0a1
|
|
442
|
+
[0.5.0a1]: https://github.com/ffroliva/gflow-cli/compare/v0.4.0a2...v0.5.0a1
|
|
313
443
|
[0.3.0a1]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.3.0a1
|
|
314
444
|
[0.2.0a1]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.2.0a1
|
|
315
445
|
[0.1.0]: https://github.com/ffroliva/gflow-cli/releases/tag/v0.1.0
|
|
@@ -142,3 +142,66 @@ uv run gflow auth login --profile experiments # named profile
|
|
|
142
142
|
- [docs/INDEX.md](docs/INDEX.md) — full doc routing
|
|
143
143
|
- [PLAN.md](PLAN.md) — implementation roadmap with phases & ADRs
|
|
144
144
|
- [.claude/README.md](.claude/README.md) — what's in `.claude/` and how to extend it
|
|
145
|
+
|
|
146
|
+
# context-mode — MANDATORY routing rules
|
|
147
|
+
|
|
148
|
+
You have context-mode MCP tools available. These rules are NOT optional — they protect your context window from flooding. A single unrouted command can dump 56 KB into context and waste the entire session.
|
|
149
|
+
|
|
150
|
+
## BLOCKED commands — do NOT attempt these
|
|
151
|
+
|
|
152
|
+
### curl / wget — BLOCKED
|
|
153
|
+
Any Bash command containing `curl` or `wget` is intercepted and replaced with an error message. Do NOT retry.
|
|
154
|
+
Instead use:
|
|
155
|
+
- `ctx_fetch_and_index(url, source)` to fetch and index web pages
|
|
156
|
+
- `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` to run HTTP calls in sandbox
|
|
157
|
+
|
|
158
|
+
### Inline HTTP — BLOCKED
|
|
159
|
+
Any Bash command containing `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, or `http.request(` is intercepted and replaced with an error message. Do NOT retry with Bash.
|
|
160
|
+
Instead use:
|
|
161
|
+
- `ctx_execute(language, code)` to run HTTP calls in sandbox — only stdout enters context
|
|
162
|
+
|
|
163
|
+
### WebFetch — BLOCKED
|
|
164
|
+
WebFetch calls are denied entirely. The URL is extracted and you are told to use `ctx_fetch_and_index` instead.
|
|
165
|
+
Instead use:
|
|
166
|
+
- `ctx_fetch_and_index(url, source)` then `ctx_search(queries)` to query the indexed content
|
|
167
|
+
|
|
168
|
+
## REDIRECTED tools — use sandbox equivalents
|
|
169
|
+
|
|
170
|
+
### Bash (>20 lines output)
|
|
171
|
+
Bash is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `npm install`, `pip install`, and other short-output commands.
|
|
172
|
+
For everything else, use:
|
|
173
|
+
- `ctx_batch_execute(commands, queries)` — run multiple commands + search in ONE call
|
|
174
|
+
- `ctx_execute(language: "shell", code: "...")` — run in sandbox, only stdout enters context
|
|
175
|
+
|
|
176
|
+
### Read (for analysis)
|
|
177
|
+
If you are reading a file to **Edit** it → Read is correct (Edit needs content in context).
|
|
178
|
+
If you are reading to **analyze, explore, or summarize** → use `ctx_execute_file(path, language, code)` instead. Only your printed summary enters context. The raw file content stays in the sandbox.
|
|
179
|
+
|
|
180
|
+
### Grep (large results)
|
|
181
|
+
Grep results can flood context. Use `ctx_execute(language: "shell", code: "grep ...")` to run searches in sandbox. Only your printed summary enters context.
|
|
182
|
+
|
|
183
|
+
## Tool selection hierarchy
|
|
184
|
+
|
|
185
|
+
1. **GATHER**: `ctx_batch_execute(commands, queries)` — Primary tool. Runs all commands, auto-indexes output, returns search results. ONE call replaces 30+ individual calls.
|
|
186
|
+
2. **FOLLOW-UP**: `ctx_search(queries: ["q1", "q2", ...])` — Query indexed content. Pass ALL questions as array in ONE call.
|
|
187
|
+
3. **PROCESSING**: `ctx_execute(language, code)` | `ctx_execute_file(path, language, code)` — Sandbox execution. Only stdout enters context.
|
|
188
|
+
4. **WEB**: `ctx_fetch_and_index(url, source)` then `ctx_search(queries)` — Fetch, chunk, index, query. Raw HTML never enters context.
|
|
189
|
+
5. **INDEX**: `ctx_index(content, source)` — Store content in FTS5 knowledge base for later search.
|
|
190
|
+
|
|
191
|
+
## Subagent routing
|
|
192
|
+
|
|
193
|
+
When spawning subagents (Agent/Task tool), the routing block is automatically injected into their prompt. Bash-type subagents are upgraded to general-purpose so they have access to MCP tools. You do NOT need to manually instruct subagents about context-mode.
|
|
194
|
+
|
|
195
|
+
## Output constraints
|
|
196
|
+
|
|
197
|
+
- Keep responses under 500 words.
|
|
198
|
+
- Write artifacts (code, configs, PRDs) to FILES — never return them as inline text. Return only: file path + 1-line description.
|
|
199
|
+
- When indexing content, use descriptive source labels so others can `ctx_search(source: "label")` later.
|
|
200
|
+
|
|
201
|
+
## ctx commands
|
|
202
|
+
|
|
203
|
+
| Command | Action |
|
|
204
|
+
|---------|--------|
|
|
205
|
+
| `ctx stats` | Call the `ctx_stats` MCP tool and display the full output verbatim |
|
|
206
|
+
| `ctx doctor` | Call the `ctx_doctor` MCP tool, run the returned shell command, display as checklist |
|
|
207
|
+
| `ctx upgrade` | Call the `ctx_upgrade` MCP tool, run the returned shell command, display as checklist |
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# gflow-cli Configuration Reference
|
|
2
|
+
|
|
3
|
+
## Environment variables
|
|
4
|
+
|
|
5
|
+
| Env var | Default | Description |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| `GFLOW_CLI_HOME` | Platform data dir | Root directory for profiles and config. |
|
|
8
|
+
| `GFLOW_CLI_OUTPUT_DIR` | `~/Downloads/gflow-cli` | Where generated images and videos are saved. |
|
|
9
|
+
| `GFLOW_CLI_BROWSER` | `auto` | Browser mode. See **Browser mode** section below. |
|
|
10
|
+
| `CHROME_BINARY` | (autodetect) | Override Chrome binary path. Falls back to platform-standard locations. |
|
|
11
|
+
| `GFLOW_CLI_CONCURRENCY` | `4` | Maximum parallel API requests per batch. |
|
|
12
|
+
| `GFLOW_LIVE` | _(unset)_ | Set to `1` to enable live-API test markers (`@pytest.mark.live`). |
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Browser mode (D.2.3+)
|
|
17
|
+
|
|
18
|
+
| Env var | Default | Description |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `GFLOW_CLI_BROWSER` | `auto` | `auto` attaches to running Chrome via CDP or spawns detached; `fresh` launches new Playwright Chromium per call (legacy); `cdp:<port>` attaches to explicit CDP endpoint. |
|
|
21
|
+
| `CHROME_BINARY` | (autodetect) | Override Chrome binary path. Falls back to platform-standard locations. |
|
|
22
|
+
|
|
23
|
+
### When to use which
|
|
24
|
+
|
|
25
|
+
- **`auto`** (recommended): real Chrome fingerprint = highest reCAPTCHA risk score; persistent
|
|
26
|
+
across CLI invocations. First call spawns Chrome detached; subsequent calls attach via CDP.
|
|
27
|
+
- **`fresh`**: legacy single-shot Playwright Chromium. Use when you need a clean profile per call.
|
|
28
|
+
- **`cdp:<port>`**: connect to an already-running Chrome you spawned yourself
|
|
29
|
+
(e.g. with `--remote-debugging-port=9222`).
|
|
30
|
+
|
|
31
|
+
### Chrome binary autodetection order
|
|
32
|
+
|
|
33
|
+
1. `CHROME_BINARY` env var (checked first — always wins)
|
|
34
|
+
2. `shutil.which("chrome")` / `shutil.which("google-chrome")` / `shutil.which("chromium")`
|
|
35
|
+
3. Platform-standard paths:
|
|
36
|
+
- **Windows**: `C:\Program Files\Google\Chrome\Application\chrome.exe`,
|
|
37
|
+
`C:\Program Files (x86)\Google\Chrome\Application\chrome.exe`,
|
|
38
|
+
`%LOCALAPPDATA%\Google\Chrome\Application\chrome.exe`
|
|
39
|
+
- **macOS**: `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`
|
|
40
|
+
- **Linux**: `/usr/bin/google-chrome`, `/usr/bin/chromium`, `/usr/bin/chromium-browser`
|
|
41
|
+
|
|
42
|
+
If Chrome is not found, gflow-cli raises a `ConfigurationError` with an install hint.
|
|
43
|
+
|
|
44
|
+
### CDP port range
|
|
45
|
+
|
|
46
|
+
By default gflow-cli uses CDP port `9222`. If that port is occupied by a non-gflow Chrome,
|
|
47
|
+
it probes `9222–9229` until a free port is found. The chosen port is persisted in
|
|
48
|
+
`<profile_dir>/.gflow-cdp.lock` so subsequent calls reuse the same port.
|
|
49
|
+
|
|
50
|
+
If all 8 ports are occupied, a `ConfigurationError` is raised.
|
|
51
|
+
|
|
52
|
+
### Lockfile
|
|
53
|
+
|
|
54
|
+
`<profile_dir>/.gflow-cdp.lock` — JSON file containing `{pid, port, profile_name}`.
|
|
55
|
+
Written atomically (tmp + `os.link`, `O_CREAT|O_EXCL|O_NOFOLLOW`, mode `0o600`)
|
|
56
|
+
when Chrome is first spawned. Stale locks (PID no longer alive) are cleaned up
|
|
57
|
+
automatically on the next CLI invocation.
|
|
58
|
+
|
|
59
|
+
### Security note — localhost CDP trust model
|
|
60
|
+
|
|
61
|
+
The Chrome DevTools Protocol endpoint (`http://localhost:<port>/json/version`)
|
|
62
|
+
is **not authenticated**. Any process on the same machine that can reach
|
|
63
|
+
`localhost:9222` can drive the browser. gflow-cli treats a port owner that
|
|
64
|
+
matches our lockfile as trusted; an unmanaged Chrome on the same port is
|
|
65
|
+
attached with a `attached_to_unmanaged_chrome=true` warning logged.
|
|
66
|
+
|
|
67
|
+
**Do not run gflow-cli on a shared multi-user machine** where untrusted users
|
|
68
|
+
have shell access. Use a dedicated user account or a VM per worker.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gflow-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0a1
|
|
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
|
|
@@ -69,7 +69,7 @@ Description-Content-Type: text/markdown
|
|
|
69
69
|
|
|
70
70
|
> ⚠️ **Not affiliated with Google.** Reverse-engineered from public Flow web traffic. Endpoints can change at any time. See full [DISCLAIMER](DISCLAIMER.md) before use.
|
|
71
71
|
|
|
72
|
-
📚 **Docs:** [INDEX](docs/INDEX.md) · [User Guide](docs/USER_GUIDE.md) · [Architecture](docs/ARCHITECTURE.md) · [Authentication](docs/AUTHENTICATION.md) · [Configuration](docs/CONFIGURATION.md) · [Usage](docs/USAGE.md) · [Security](docs/SECURITY.md) · [Known issues](KNOWN_ISSUES.md) · [Plan](PLAN.md) · [Changelog](CHANGELOG.md)
|
|
72
|
+
📚 **Docs:** [INDEX](docs/INDEX.md) · [User Guide](docs/USER_GUIDE.md) · [Architecture](docs/ARCHITECTURE.md) · [Authentication](docs/AUTHENTICATION.md) · [Configuration](docs/CONFIGURATION.md) · [Usage](docs/USAGE.md) · [Security](docs/SECURITY.md) · [Known issues](KNOWN_ISSUES.md) · [Release protocol](RELEASE.md) · [Plan](PLAN.md) · [Changelog](CHANGELOG.md)
|
|
73
73
|
🤖 **For AI agents:** [CLAUDE.md](CLAUDE.md) · [`.claude/`](.claude/README.md)
|
|
74
74
|
|
|
75
75
|
---
|
|
@@ -108,7 +108,7 @@ Read the full [DISCLAIMER](DISCLAIMER.md) before deploying this in any productio
|
|
|
108
108
|
|
|
109
109
|
## Project status
|
|
110
110
|
|
|
111
|
-
**v0.
|
|
111
|
+
**v0.5.0a1 — alpha.** Video (T2V/I2V/batch), image (T2I/I2I/upload), the new **`gflow run` JSON-batch command**, and the **`ui_automation` default transport** are functional end-to-end against a live Google AI Pro/Ultra Flow account. Three earlier HTTP transport strategies (`evaluate_fetch` / `bearer` / `sapisidhash`) move to an `experimental/` subpackage in this release; the production path is `ui_automation`.
|
|
112
112
|
|
|
113
113
|
| Milestone | Status |
|
|
114
114
|
|---|---|
|
|
@@ -122,7 +122,36 @@ Read the full [DISCLAIMER](DISCLAIMER.md) before deploying this in any productio
|
|
|
122
122
|
| Typed errors (RFC 9457 Problem Details) + per-class exit codes 3–7 | ✅ done (v0.4.0a2) |
|
|
123
123
|
| Retry / backoff + reCAPTCHA re-mint inside the retry loop | ✅ done (v0.4.0a2) |
|
|
124
124
|
| Structured logs (`structlog`, JSON on pipe) | ✅ done (v0.4.0a2) |
|
|
125
|
-
|
|
|
125
|
+
| Pluggable image transport + `ui_automation` default strategy | ✅ done (v0.5.0a1) |
|
|
126
|
+
| `gflow run --config <file>` sequential JSON batches | ✅ done (v0.5.0a1) |
|
|
127
|
+
| `examples/` directory with runnable single-image + batch scripts | ✅ done (v0.5.0a1) |
|
|
128
|
+
| Shell multi-prompt `gflow image t2i` (`PROMPT...`, `--prompts-file`, `--stdin`) | ✅ done (v0.6.0a1) |
|
|
129
|
+
| Provider abstraction for official Veo 3.1 API | ⏳ planned (v0.6+) |
|
|
130
|
+
|
|
131
|
+
### What's new in v0.5.0a1
|
|
132
|
+
|
|
133
|
+
- `UiAutomationTransport` is now the default image-generation strategy — Playwright-driven UI mimicry against the Flow editor on a logged-in Pro/Ultra profile (no externally-exposed CDP debug port).
|
|
134
|
+
- New top-level `gflow run --config <file>` command for JSON-described sequential batches (1–50 prompts per file, `--continue-on-error` / `--fail-fast` modes). See [`docs/USAGE.md`](docs/USAGE.md#gflow-run) for the schema.
|
|
135
|
+
- Three runnable example scripts shipped under [`examples/`](examples/README.md) — copy and edit for your own pipelines.
|
|
136
|
+
- See the full [CHANGELOG](CHANGELOG.md#0501) for the security follow-ups (download host allow-list, viewport-only debug screenshots) and the listener-attach race fix.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Demo
|
|
141
|
+
|
|
142
|
+

|
|
143
|
+
|
|
144
|
+
*A single `gflow image t2i "..." --aspect 9:16 --model nano2 --out ...` call against a logged-in Pro/Ultra profile. The terminal shows the streaming `structlog` JSON for the run, the final `ls` of the written PNG, and nothing else — Chromium drives the Flow editor silently in the background because the persistent Playwright session is already warm, so this take is intentionally terminal-only.*
|
|
145
|
+
|
|
146
|
+
**Try it yourself** — this is the exact command the GIF runs:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
gflow image t2i "a quiet mountain lake at dawn, cinematic photography" --aspect 9:16 --model nano2 --out ./gflow-output/example-single
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
One prompt, default model (`nano2` = Nano Banana 2), 9:16 portrait, written as `./gflow-output/example-single/<media_name>_0.png`. Wall time is typically 30–90s on a warm profile; the first call after a fresh `gflow auth login` is slower because Playwright spins up Chromium and navigates to the Flow editor. See [`docs/USAGE.md`](docs/USAGE.md) for the full `gflow image t2i` flag reference (`--model`, `--aspect`, `-n`, `--seed`, `--profile`, `--transport`).
|
|
153
|
+
|
|
154
|
+
To reproduce the recording yourself, see [`scripts/record_demo.ps1`](scripts/record_demo.ps1) (Windows, requires OBS + ffmpeg + gifski).
|
|
126
155
|
|
|
127
156
|
---
|
|
128
157
|
|
|
@@ -233,7 +262,9 @@ gflow auth login # one-time browser sign
|
|
|
233
262
|
gflow auth status # show current session
|
|
234
263
|
|
|
235
264
|
gflow image upload <path> # upload PNG/JPEG → asset UUID
|
|
236
|
-
gflow image t2i "<prompt>" [--model] [--aspect]
|
|
265
|
+
gflow image t2i "<prompt>" [...] [--model] [--aspect] # text-to-image; repeat prompts for a warm batch
|
|
266
|
+
gflow image t2i --prompts-file prompts.txt # text-file multi-prompt batch
|
|
267
|
+
gflow image t2i --stdin # stdin multi-prompt batch
|
|
237
268
|
gflow image i2i "<prompt>" --ref PATH_OR_UUID [...] # image-to-image (1–4 per call)
|
|
238
269
|
|
|
239
270
|
gflow video t2v "<prompt>" -o out.mp4 # text-to-video (Veo 3.1)
|
|
@@ -376,17 +407,20 @@ Each `Provider` method has a corresponding test file under `tests/`. New routes
|
|
|
376
407
|
|
|
377
408
|
1. Update [`CHANGELOG.md`](CHANGELOG.md) with the version's changes (Keep-a-Changelog format).
|
|
378
409
|
2. Bump `version` in `pyproject.toml`.
|
|
379
|
-
3.
|
|
410
|
+
3. Bump `__version__` in `src/gflow_cli/__init__.py`.
|
|
411
|
+
4. Tag the commit:
|
|
380
412
|
```bash
|
|
381
|
-
git tag
|
|
382
|
-
git push origin
|
|
413
|
+
git tag v<version> # for example, v0.4.0 or v0.4.0a3
|
|
414
|
+
git push origin v<version>
|
|
383
415
|
```
|
|
384
|
-
|
|
416
|
+
5. The [`release.yml`](.github/workflows/release.yml) GitHub Action runs:
|
|
385
417
|
- Builds the wheel + sdist with `uv build`
|
|
386
418
|
- Publishes to PyPI via [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) — no API tokens stored
|
|
387
419
|
- Creates a GitHub Release with the changelog excerpt + built artifacts attached
|
|
388
420
|
|
|
389
|
-
|
|
421
|
+
PEP 440 prerelease tags (`vX.Y.ZaN`, `vX.Y.ZbN`, `vX.Y.ZrcN`) and hyphenated prerelease tags (`vX.Y.Z-alphaN`, `vX.Y.Z-betaN`, `vX.Y.Z-rcN`) auto-flag as prereleases on GitHub. Stable tags such as `v0.4.0` become full GitHub Releases. See [RELEASE.md](RELEASE.md) for the checklist and the prerelease/full-release policy.
|
|
422
|
+
|
|
423
|
+
Install prereleases explicitly with `pip install --pre gflow-cli` or `uvx --from "gflow-cli==0.4.0a2" gflow`.
|
|
390
424
|
|
|
391
425
|
---
|
|
392
426
|
|
|
@@ -422,6 +456,5 @@ Note that the **Google service** this tool talks to has its own terms (Google La
|
|
|
422
456
|
[](https://github.com/ffroliva/gflow-cli/commits/main)
|
|
423
457
|
[](https://github.com/ffroliva/gflow-cli)
|
|
424
458
|
[](https://pypi.org/project/gflow-cli/)
|
|
425
|
-
[](https://pypi.org/project/gflow-cli/)
|
|
426
459
|
|
|
427
460
|
If `gflow-cli` saves you time, please ⭐ the repo — it's the cheapest way to support the project.
|