Skip to content

Add agent signup and improve config-resolution diagnostics#117

Open
const-cloudinary wants to merge 4 commits into
masterfrom
agent-signup-and-config-ux
Open

Add agent signup and improve config-resolution diagnostics#117
const-cloudinary wants to merge 4 commits into
masterfrom
agent-signup-and-config-ux

Conversation

@const-cloudinary

@const-cloudinary const-cloudinary commented Jul 1, 2026

Copy link
Copy Markdown
Member

Summary

Adds the cld agent signup command: for AI agents, it creates a Free-plan Cloudinary account on behalf of a human, saves the returned product environment as a named config, and detects duplicate signups both locally (from saved configs) and server-side.

cld agent signup <email> <agent_framework> <agent_llm_model> <agent_goal>

Flags: --name, --set-default, --no-save, --sdk-framework, --json. Credentials are inert until the human completes the emailed verification.

Also improves config-resolution UX slightly: unconfigured/no-default/incomplete states now report the true situation with clearer guidance, and commands that need no config no longer print the "no configuration found" banner.

Docs

README: added agent signup to the important-commands list and a dedicated section documenting syntax, example, and flags.

Testing

  • pytest test/ --ignore=test/test_modules → 332 passed, 21 skipped.
  • pyflakes clean on all touched files.
  • The test/test_modules/* collection error is pre-existing (those modules need real credentials at import) and unrelated to this change.

Manual checks

Isolate the config dir and clear Cloudinary env first so nothing touches a real account:

export CLOUDINARY_HOME="$(mktemp -d)/.cloudinary-cli"
for v in $(env | grep -o '^CLOUDINARY_URL'); do unset "$v"; done
# real signup (rate-limited, sends a verification email, creates a real Free account)
cld agent signup you+test@example.com claude-code claude-fable-5 "smoke test"
cld agent signup you+test@example.com claude-code claude-fable-5 "goal" --json     # raw JSON contract
cld agent signup you+test@example.com claude-code claude-fable-5 "goal" --no-save  # show creds, don't save

# input validation (no API call)
cld agent signup "" claude-code claude-fable-5 "goal"                     # empty email -> exit 2
cld agent signup you+t@example.com claude-code claude-fable-5 "goal" --name __default__  # reserved -> exit 2

# config-resolution UX
cld config -ls                        # empty -> guidance (incl. agent signup), not an empty table
cld url sample                        # unconfigured -> clean banner, no "warning:" prefix
cld -c not-a-url admin usage          # -> "expects a CLOUDINARY_URL" (exit 2)

Note: agent signup was exercised via mocked tests; the live provisioning API path (which creates real accounts and sends verification emails) was not run in CI.

🤖 Generated with Claude Code

const-cloudinary and others added 3 commits July 1, 2026 17:20
Add `cld agent signup <email> <framework> <model> <goal>`: creates a
Free-plan account on behalf of a human, saves the returned environment
as a named config, and detects duplicate signups locally and server-side.

Make config resolution report the true state instead of a blanket
"No configuration found":
- Commands that own or need no config (login, logout, config, agent) no
  longer print the banner (config_optional decorator).
- Saved configs but no default set -> "No default configuration is set".
- An explicitly selected but credential-less config (-c/-C) -> "incomplete".
- -c/--config validates its argument up front and points to -C when given
  a saved config name.
- The unconfigured guidance prints clean (no "warning:" prefix) and lists
  `agent signup`; empty `config -ls` shows it instead of an empty table.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The group banner now prints to stderr (and is suppressed for `config`,
which is config-optional), so bare `cld config` on the unconfigured path
reports "No Cloudinary configuration found" via its own raised
ConfigurationError rather than stdout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TestUnconfiguredBanner stripped only CLOUDINARY_URL and built the fresh
SDK config as a with-statement argument evaluated before the env was
cleared, so a developer's exported CLOUDINARY_URL leaked in and the
"unconfigured" assertions failed. Strip every CLOUDINARY_* and call
reset_config inside the patched context, matching the other suites.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@const-cloudinary const-cloudinary requested a review from njb90 July 1, 2026 14:30
The module cloudinary_cli.core.agent and its exported Group both named
`agent`, so `from .agent import agent` shadowed the submodule on the core
package. On Python 3.10, mock.patch("cloudinary_cli.core.agent.<attr>")
resolved the dotted path to the Group object instead of the module and
raised AttributeError/ModuleNotFoundError at patch time. Rename the symbol
to `agent_group` (module and CLI name unchanged), matching the module-name
!= exported-symbol convention already used by config/auth.

Also patch cloudinary.provisioning.create_agent_account at its canonical
location rather than through the core.agent chain.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant