feat: add poly functions commands and grouped CLI help (DEVP-541, DEVP-543) - #245
feat: add poly functions commands and grouped CLI help (DEVP-541, DEVP-543)#245andymohajeri wants to merge 5 commits into
Conversation
Surfaces the public Functions REST API in the ADK so developers can manage Functions programmatically, following the existing audio-cache/conversations command pattern: - poly functions list/get/create/update/delete/execute/duplicate - poly functions deploy/validate/references/type-definitions/deployments - poly functions start|end get/update for the branch lifecycle hooks - PlatformAPIHandler/AgentStudioInterface methods for the above, with 409 conflicts translated into FunctionConflictError carrying the orphaned flow-step references - print_functions/print_function_* and print_code helpers in console.py - Handler tests (platform_api_test.py) and CLI tests (cli_test.py) - cli.md reference docs, plus a cross-reference from the local-file Functions docs distinguishing the two mechanisms Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
b260b1c to
10d24c1
Compare
This comment has been minimized.
This comment has been minimized.
10d24c1 to
9444f08
Compare
This comment has been minimized.
This comment has been minimized.
9444f08 to
279a307
Compare
This comment has been minimized.
This comment has been minimized.
279a307 to
3638899
Compare
This comment has been minimized.
This comment has been minimized.
argparse has no built-in support for section headers within a subparsers
group, so the command lists were flat and getting hard to scan (23 at the top
level, 14 under `poly functions`, 9 under `poly branch`). Adds the general
mechanism the ticket describes as option 2 — a custom HelpFormatter driven by a
per-parser {subcommand: group} mapping — so each subcommand's own `help=` stays
the single source of truth.
Applied to every parser with a crowded subcommand list:
- `poly --help`: Getting started / Project sync / Builder API / Other
- `poly functions --help`: Manage / Run and inspect / Deploy / Lifecycle hooks
- `poly branch --help`: Branch lifecycle / Inspect
Mechanism, all in cli_commands/base.py:
- add_grouped_subparsers() creates the subparsers action, drops the outer
"positional arguments:" heading and hoists the commands above the options
- group_subcommands(subparsers, {name: group}, order, fallback) reorders the
help entries and injects header rows; a subcommand with an unmapped or
misspelled group falls back to a trailing section rather than vanishing
- _GroupedHelpMixin hides the redundant metavar placeholder line and tidies the
whitespace the header mechanism leaves behind, mixed into both a plain and a
raw-text formatter so parsers with hand-formatted descriptions still work
- BaseCommand gains a `group` attribute for the top-level listing
Note: PR #247 concurrently rewrites branch.py and takes it from 9 to 15
subcommands, so whoever merges second resolves a conflict there and extends
BRANCH_SUBCOMMAND_GROUPS with the new subcommands. The coverage test fails
until they do, so it cannot be missed silently.
Parsing, error messages and shell completion are unchanged. Tests assert each
grouped parser's mapping covers every subcommand it registers.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
3638899 to
5ae1832
Compare
This comment has been minimized.
This comment has been minimized.
josephcesarperez
left a comment
There was a problem hiding this comment.
lgtm functionally, just curious about the context for why we are introducing the usecase splitting out from the usual local pull push workflow
Ruari-Phipps
left a comment
There was a problem hiding this comment.
Yeah following on from what Joey said.
I think we need to allow for some commands to be handed account_id, project_id, region, branch_id directly rather than loading it from local file system.
Mainly the functions one here but we could also allow it for others
delete_function always sent {"force": force} even when False, unlike
every other DELETE call in this handler. duplicate_function treated an
explicit empty-string name the same as omitting it, silently dropping
the value.
This comment has been minimized.
This comment has been minimized.
…mands Address PR #245 review feedback (Ruari-Phipps): - poly functions subcommands now accept --region/--project_id/--branch_id directly (all-or-nothing), bypassing the local project checkout entirely. Mirrors the existing `poly project` precedent for pre-checkout flags. Adds resolve_project_scope() in shared.py to pick explicit flags over load_project() when given. - Move rtc/test/chat out of the "Builder API" --help section into "Project sync", since they operate on local project/branch state rather than being pure remote-API calls like functions/audio-cache/ conversations/deployments. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
|
@josephcesarperez re: why split this off instead of the standard push/pull workflow — three main reasons:
To be clear, this isn't replacing anything — the existing local |
…nctions-api-into-adk # Conflicts: # src/poly/cli_commands/branch.py # src/poly/handlers/interface.py # src/poly/tests/cli_test.py
Coverage Report
Changed file coverage
|
Summary
Adds a
poly functionscommand group wrapping the public Functions REST API, so developers can manage Functions programmatically instead of only through the local-file/decorator workflow. Also groups the CLI's subcommand listings under section headers, since this PR pushes the top-level command count to 23.Motivation
A new public Functions REST API was built across
platform_ui(Sourcerer/agent-stream) andpoly_core. This surfaces it in the ADK for headless/programmatic use.Note: the ADK already has a "functions" concept (
poly/resources/function.py) — local.pyfiles with@func_description/@func_parameterdecorators, synced via gRPC/protobuf throughpush/pull. That mechanism is unrelated and untouched here; the two are intentionally kept separate, with a docs cross-reference so the distinction is discoverable. Unifying them is a likely follow-up.DEVP-543 is bundled in at reviewer request. The two changes are independent and are separate commits.
Changes
poly functions(DEVP-541)Follows the
audio-cache/conversationscommand pattern.src/poly/cli_commands/functions.py(new):FunctionsCommandwithlist,get,create,update,delete,execute,duplicate,deploy,validate,references,type-definitions,deployments, andstart/endfor the branch lifecycle hooks. All support--json. Registered incli.pyvia the usual 2-line import +COMMANDSentry.src/poly/handlers/platform_api.py:FUNCTIONS_*URL constants and the correspondingPlatformAPIHandlermethods. 409 conflicts (orphaned flow-step references, name collisions) are translated intoFunctionConflictError, aValueErrorsubclass carryingorphaned_referencesso--forceand the CLI's conflict reporting can use them.src/poly/handlers/interface.py:AgentStudioInterfacepassthroughs.src/poly/output/console.py:print_functions,print_function_detail,print_function_references,print_function_deployments,print_function_validation_issues, and a sharedprint_code.poly functionssection indocs/docs/reference/cli.md, plus a cross-reference from the local-file Functions docs.Unreadable
--code-filepaths and malformed--parameters/--argsJSON exit with a clear message rather than a traceback.Grouped
--helpsections (DEVP-543)argparse has no built-in support for section headers within a subparsers group. Implements the ticket's option 2 — a custom
HelpFormatterdriven by a per-parser{subcommand: group}mapping — so each subcommand's ownhelp=stays the single source of truth.poly --help: Getting started / Project sync / Builder API / Otherpoly functions --help: Manage / Run and inspect / Deploy / Lifecycle hookspoly branch --help: Branch lifecycle / InspectMechanism lives in
cli_commands/base.py:add_grouped_subparsers()creates the subparsers action and drops the outerpositional arguments:heading;group_subcommands()reorders the help entries and injects header rows;_GroupedHelpMixinhides the redundant metavar placeholder and tidies whitespace, mixed into both a plain and a raw-text formatter so parsers with hand-formatted descriptions still work.BaseCommandgains agroupattribute.Parsing, error messages and shell completion are unchanged.
Overlap with #247: that PR concurrently rewrites
branch.pyand takes it from 9 to 15 subcommands, so whoever merges second resolves a conflict inbranch.py,interface.pyandcli_test.py(the latter two are append-adjacent — take both sides) and extendsBRANCH_SUBCOMMAND_GROUPSwith the new subcommands. The coverage test fails until they do, so it can't be missed silently.Reviewer note: this necessarily touches three semi-private argparse attributes (
_choices_actions,_action_groups, and a_format_actionoverride) — the ticket anticipates this for option 2. Each has a comment explaining the mechanism, and the tests assert on rendered output so a future Python change fails loudly rather than silently degrading.Test strategy
poly <command>) —--helpfor every new command and subcommand, plus both error paths (missing and invalid subcommand) on each grouped parserdevbefore merge.Handler tests live in
src/poly/tests/api/platform_api_test.py, CLI tests insrc/poly/tests/cli_test.py. Coverage includes the 409-conflict paths (create/update/delete/duplicate), the 204-empty-body delete, and the input-validation exits. Each grouped parser has a test asserting its mapping covers every subcommand it registers, so adding one without grouping it fails CI.Checklist
ruff check .andruff format --check .passpytestpasses (1053 passed)polyCLI interface —poly functionsis new, and the--helpchange is presentationalScreenshots / Logs
poly --help:poly functions --help:🤖 Generated with Claude Code