Skip to content

feat(sdk): add --field option to api command with proto-aware completion#1195

Draft
dqn wants to merge 7 commits into
mainfrom
feat/api-field-option
Draft

feat(sdk): add --field option to api command with proto-aware completion#1195
dqn wants to merge 7 commits into
mainfrom
feat/api-field-option

Conversation

@dqn
Copy link
Copy Markdown
Contributor

@dqn dqn commented May 19, 2026

Summary

Add tailor-sdk api <endpoint> -f key=value so users can set request-body
fields without writing JSON, with proto-driven tab completion of field
names (including dotted nested paths) across bash / zsh / fish.

Main changes

  • --field / -f (repeatable) on api. Dotted keys build nested
    objects (-f application.name=foo); --field overrides matching keys
    in --body. Values are strings only — use --body for non-string
    scalars.
  • Proto-driven completion of nested message fields: -f application.<TAB>
    lists children of application, = is appended on leaves and . on
    messages. Enum-typed and bool-typed leaves additionally surface their
    value set inline (e.g. role=TEAM_ROLE_ADMIN, disabled=true).
    Previously-supplied keys are de-duped per-invocation via politty's
    _used_field_keys tracker.
  • Candidates are pre-enumerated at script-generation time and inlined
    into the shell completion script via politty's expand variant —
    TAB looks them up from the inlined table keyed on the endpoint
    positional, with no Node process spawn per keystroke.
  • Override politty to https://pkg.pr.new/politty@353 for the expand
    • _used_field_keys support. Existing completion tests adapted to
      the new async generateCandidates(ctx, { shell }) signature.

Performance

Per-TAB latency for tailor-sdk api GetFunctionExecution -f <TAB>
(bash completion sourced in a loop, gdate wall clock):

Variant per TAB n script size
resolve (politty's JS resolver; spawns __complete in Node per TAB) ~952 ms 20 ~206 KB
expand (table inlined into the generated script, this PR) ~0.45 ms 500 ~356 KB

resolve-case cost is dominated by Node startup + SDK module load.

Notes

  • The politty override should be replaced with a published semver once
    feat(completion): add in-process JS resolver for dynamic value completion toiroakr/politty#353 ships. That PR has grown from ~1,500 lines
    (resolve only) to 6,000+ lines as expand and its stabilization
    fixes landed.
  • Considered keeping resolve and switching the CLI to a Bun-shipped
    binary instead of moving to expand. bun run against the same
    dist already cuts the resolve-case to ~420 ms/TAB (vs node's
    ~952 ms), and bun build --compile would shave more — but compile
    is currently blocked: the CLI eagerly loads native deps
    (oxc-parser, rolldown/oxc-resolver, @napi-rs/keyring) that
    fail to load inside Bun's bundled VFS, and fixing that needs
    lazy-loading or shimming all of them. Even an optimistic
    ~200 ms compiled-bun cold start is still ~400× the ~0.45 ms
    expand lookup, so reverting expand to keep resolve doesn't
    carry.
  • Non-object --body (e.g. '"str"') combined with --field is
    rejected — there's no sensible merge target.
  • Out of scope: oneof exclusivity, list/map index syntax.

dqn added 2 commits May 20, 2026 01:17
`completion.custom.resolve` (in-process JS resolver that sees other arg
values) is needed by the upcoming `tailor-sdk api --field` proto-aware
completion. PR toiroakr/politty#353 adds it; replace with the released
version once published.
`tailor-sdk api <endpoint> -f key=value` (`--field`) lets users set
request body fields without writing JSON. Dotted keys build nested
objects (`-f application.name=foo`); `--field` overrides matching keys
in `--body`; values are strings only. Field names tab-complete from the
endpoint's proto schema, with step-by-step completion of nested message
fields (bash / zsh / fish).

Implemented via politty's new `completion.custom.resolve` resolver,
which receives the entered endpoint as `parsedArgs.endpoint` and the
previously-supplied `-f` values for de-duplication.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 19, 2026

🦋 Changeset detected

Latest commit: fc00ae5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@tailor-platform/sdk Minor
@tailor-platform/create-sdk Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 19, 2026

⚡ pkg.pr.new

@tailor-platform/sdk

pnpm add https://pkg.pr.new/@tailor-platform/sdk@0646e0a
pnpm dlx https://pkg.pr.new/@tailor-platform/sdk@0646e0a --help

@tailor-platform/create-sdk

pnpm add https://pkg.pr.new/@tailor-platform/create-sdk@0646e0a
pnpm dlx https://pkg.pr.new/@tailor-platform/create-sdk@0646e0a my-app

commit: 0646e0a

@github-actions

This comment has been minimized.

dqn added 4 commits May 20, 2026 01:38
Adds value-side completion to `tailor-sdk api -f key=value`: enum-typed
fields offer their value names and bool-typed fields offer `true`/`false`,
inferred from the endpoint's proto schema. Scalar, message, list, and map
fields stay free-form.
…uild

pnpm caches `pkg.pr.new` URLs in three layers (store index DB, lockfile,
hoisted node_modules) and `pnpm install --force` / `update` /
`--fix-lockfile` alone can't pull in a refreshed PR tarball. Adding a
`?v=YYYYMMDD` query parameter to the override URL forces a new cache key.
Bump this value whenever PR #353 is repushed.
The previous cache-buster (?v=20260521) ended up serving a stale build
that pre-dated the dedup commit on politty's PR. Bump to ?v=20260522 to
force pnpm to refetch and pick up the `_used_field_keys` tracker that
de-dupes repeated `-f key=value` slots.
Switch the `--field` completion from politty's dynamic JS resolver to the
new `expand` variant. Candidates (key=, key=ENUM_VALUE, key=true/false,
key. drill-down) are enumerated once at script-generation time and
inlined into the shell completion script keyed by the `endpoint`
positional. TAB no longer spawns a Node process — the shell dispatches
via a static lookup table, and politty's `_used_field_keys` tracker
dedupes repeated key= slots within a single `api` invocation.
@github-actions
Copy link
Copy Markdown

Code Metrics Report (packages/sdk)

main (d3d984f) #1195 (32ef49f) +/-
Coverage 61.9% 62.0% +0.1%
Code to Test Ratio 1:0.4 1:0.4 +0.0
Details
  |                    | main (d3d984f) | #1195 (32ef49f) |  +/-  |
  |--------------------|----------------|-----------------|-------|
+ | Coverage           |          61.9% |           62.0% | +0.1% |
  |   Files            |            363 |             363 |     0 |
  |   Lines            |          12651 |           12701 |   +50 |
+ |   Covered          |           7833 |            7881 |   +48 |
+ | Code to Test Ratio |          1:0.4 |           1:0.4 |  +0.0 |
  |   Code             |          82915 |           83195 |  +280 |
+ |   Test             |          34645 |           34810 |  +165 |

Code coverage of files in pull request scope (94.7% → 95.1%)

Files Coverage +/- Status
packages/sdk/src/cli/commands/api/index.ts 92.6% +0.1% modified
packages/sdk/src/cli/commands/api/proto-reflect.ts 96.8% +13.5% modified
packages/sdk/src/cli/commands/api/render.ts 96.9% -0.2% modified

SDK Configure Bundle Size

main (d3d984f) #1195 (32ef49f) +/-
configure-index-size 17KB 17KB 0KB
dependency-chunks-size 34.43KB 34.43KB 0KB
total-bundle-size 51.43KB 51.43KB 0KB

Runtime Performance

main (d3d984f) #1195 (32ef49f) +/-
Generate Median 3,036ms 2,969ms -67ms
Generate Max 3,076ms 2,992ms -84ms
Apply Build Median 3,077ms 3,003ms -74ms
Apply Build Max 3,126ms 3,025ms -101ms

Type Performance (instantiations)

main (d3d984f) #1195 (32ef49f) +/-
tailordb-basic 35,130 35,130 0
tailordb-optional 3,841 3,841 0
tailordb-relation 7,428 7,428 0
tailordb-validate 2,566 2,566 0
tailordb-hooks 5,767 5,767 0
tailordb-object 12,136 12,136 0
tailordb-enum 2,462 2,462 0
resolver-basic 9,424 9,424 0
resolver-nested 26,111 26,111 0
resolver-array 18,187 18,187 0
executor-schedule 4,234 4,234 0
executor-webhook 873 873 0
executor-record 8,166 8,166 0
executor-resolver 4,369 4,369 0
executor-operation-function 869 869 0
executor-operation-gql 869 869 0
executor-operation-webhook 888 888 0
executor-operation-workflow 1,714 1,714 0

Reported by octocov

…be fix

The refreshed build drops the `--` separator before `-S ''` so `_describe`
treats the suffix as a compadd option rather than an additional name
group, restoring the no-trailing-space behavior on `key=` candidates.
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