cli: group versions & block-config, add spec --to, role-based help, friendlier env selection#7
Open
anaslabgoul wants to merge 17 commits into
Open
Conversation
Restore the grouped `versions {list,get,diff,restore}` structure for workflow, block, and edge versions, mirroring the backend /v1/workflows[/blocks|/edges]/versions/* route tree. Reverts the flattening from 18bcea4; matches the v0.2.1 release.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Accept env id/name/slug (case-insensitive) in env switch/claim with tiered precedence and explicit ambiguity/not-found errors instead of a silent fallback. Add TestMain to isolate cmd tests from the real config dir on all OSes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- workflows blocks: group the five *-config verbs under a `config` subcommand (config pull/push/diff/validate/doctor) - workflows spec: add `--to <workflow-id>` to plan/apply; hide plan-to/apply-to as deprecated aliases - env: expose `env get`; make `create` a real alias of `add` (drop the hidden duplicate command) - extractions: reorder subcommands to the shared lifecycle order used by the other primitives - reconcile api_design and sdk_parity tests with the already-collapsed `versions` group surface Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Recategorize the root --help command menu so every command sits in a role-named group (Primitives, Resources, Workflows, Organization, Account, Setup) instead of leaving backend resources (tables, secrets, projects) in the anonymous Other fallback next to the non-API local tools (setup, sync). `files` leads the renamed Resources group as the first-class resource it is. Add TestEveryTopLevelCommandIsCategorized so a future uncategorized top-level command fails loudly instead of silently landing in Other. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
retab env switch/claim resolve a server environment by id or case-insensitive name; the environment object has no slug field, and "slug" already means the local --env config profile (credential.go). Rewording removes that conflation in the help text and resolver comments. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…create Inline --capture run-id[:step-id] avoids hand-writing a captures JSON file; --run (+ --wait) creates and launches a run in one command; --from-experiment clones an existing experiment. block-id/name move to RunE enforcement so the clone path can inherit them. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
filepath.IsAbs misses POSIX-rooted paths like /tmp/out on Windows (no drive letter), letting them escape the function bundle. Also reject a leading slash: a no-op on POSIX (already IsAbs), closes the Windows gap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
All test-side: guard POSIX mode/exec-bit asserts on Windows; isolate USERPROFILE (config/registry resolve via os.UserHomeDir there) and LocalAppData (liteparse cache); assert the api-call request path via the decoded JSON field instead of a raw substring (Windows escapes \). Verified green on Windows and on a real Linux run via WSL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Serialize the OAuth bearer-token provider with a mutex: on the pure-OAuth path it is the bearer provider directly (no dashboard-context mutex in front), so concurrent SDK requests raced on the captured token and interleaved config writes. Locking also collapses a refresh thundering herd. - Send direct storage uploads through the bounded fileDownloadClient instead of http.DefaultClient (which has no timeout), so a wedged storage endpoint can't hang an upload forever in unattended scripts. Fixed in both build-tag mirrors (files.go and the oagen overlay). - Cap how much request/response body --debug copies into the dump string (256 KiB); the wire body is untouched, but dumping a large inline base64 document no longer doubles its size in memory just to print it. - Clean up the orphaned temp file when writeParseCache's atomic rename fails. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
InferMIMEData accepts a {content, mime_type} descriptor with no url (a valid
inline document input server-side), but MIMEData.MarshalJSON only emitted
{filename, url} — serializing such documents as {"filename":"","url":""}, i.e.
an empty document silently sent over the wire. Emit content/mime_type too,
with omitempty so url-only inputs are unchanged. Adds a marshalling regression
test (the existing request-shape test only asserted filename survived).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tic floor
- Request builder used `elif data:` which is falsy for `{}`/`[]`, so cancel/
complete-style endpoints that legitimately POST an empty object sent no body
at all. Use `data is not None` (4 sites, sync + async, request + stream).
- setup.py read requirements.txt / README.md relative to cwd, so `pip install .`
from another directory raised FileNotFoundError; resolve relative to __file__.
- Pin pydantic>=2: the SDK uses v2-only APIs, so a v1 environment installs
cleanly then crashes at import.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- README: `npm install @retab/node` (not `retab`); pass json_schema as a dict;
drop the dead `client.projects.extract` snippet (no such resource) while
keeping the platform/evals framing.
- Cookbook Python: unwrap the ExtractionRequest wrapper (create() takes kwargs),
load json_schema as a dict, use a real model, and fix the off-by-one asset
path (../../ -> ../../../).
- Cookbook TS: the object-form create({...}) call throws "unsupported input
type" at runtime; rewrite to the real positional signatures for extractions
and parses, and fix the asset paths.
- Node README local-dev path (open-source/sdk/... -> clients/node).
- SKILL install command missing `| sh`; goreleaser comment go 1.26.1 -> 1.25.0
(matches cli/go.mod).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…c message
parseAPIError's detail switch only handled string and map shapes, so FastAPI's
native validation envelope {"detail": [ {loc, msg, type}, ... ]} fell through
and the error degraded to the generic "Request failed (422)". Add a []any case
that stringifies the array so the real validation errors are surfaced. Adds a
regression test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… validation - Wire the existing Tables/Secrets resources onto Retab and AsyncRetab; they were implemented but never attached, so client.tables / client.secrets raised AttributeError. - prepare_mime_document: a bare file-like object without a .name (e.g. io.BytesIO) produced filename "uploaded_file" with no extension and then failed validation with "Invalid file type: uploaded_file"; sniff the bytes to recover an extension, matching the `bytes` branch. - Replace the bare asserts in the document type/extension validation with explicit raises so the checks are not stripped under `python -O`. - display.py: image `detail` is optional in the OpenAI format; use .get(...) to avoid a KeyError. Also drop a computed-then-discarded sha256. - Adds offline regression tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The quickstart notebooks didn't run: - extractions.create() was called with an ExtractionRequest(...) wrapper, but create() takes keyword args directly -> unwrapped all call sites. - 00: schemas.generate() has no `modality` param (removed); it returns a SchemaGeneration object, not a dict, so use schema.json_schema; client.models .list() doesn't exist -> replaced with a comment (no enumeration method). Every transformed code cell was validated with ast.parse and the notebooks re-validated with nbformat. Not executed against the live API (no key locally). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- parseSheetRows decoded a cell's column letters with no upper bound, then allocated a per-row slice of that size. A crafted/garbage .xlsx with a ref like "ZZZZZZZ1" (colIndex in the hundreds of millions) drove an effective OOM on `files parse|grep|inspect`. Clamp to Excel's hard limit (XFD = 16384) and drop out-of-range cells. - cleanWorkflowTableCell truncated by bytes, cutting multibyte (accented / CJK) cells mid-rune and emitting invalid UTF-8 in `tables query` output. Truncate by runes, matching the sibling truncateReviewCell. - Adds regression tests for both. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Remove four frictions hit while running model experiments: - workflows runs create: add --wait (+ --poll-interval-ms, --timeout-seconds) to block until the run reaches a terminal status, matching extractions create / experiments runs create. - workflows runs get: add --steps to fetch and embed per-block step records (the run GET endpoint does not return them server-side, so this saves a second steps-list call). - workflows blocks get: emit derived input/output handle ids so edge wiring no longer requires inspecting another workflow's edges. Inputs from config.inputs; outputs for deterministic block types only (routing handles are route-keyed). - projects create: add the command (POST /v1/projects) so 'workflows create --project-id' is satisfiable end-to-end via CLI; api_design command-surface test updated accordingly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A focused pass over the CLI command surface and its
--helppresentation,making the command tree mirror the backend resource model more closely and
simplifying several rough edges. Net change is +494 / −710 (a
simplification). All commits touch only
cli/cmd/.What changed
workflows versions {list,get,diff,restore}— replaces the four flatverbs (
versions/diff/version/version-restore) and their dualpositional/flag resolvers with one cohesive group. Mirrors the SDK
(
ListVersions/GetVersion/ListDiff/CreateVersionRestore).workflows blocks config {pull,push,diff,validate,doctor}— groups thefive flat
*-configverbs under aconfigsubcommand.workflows spec plan|apply --to <workflow-id>— folds theplan-to/apply-tocommands into a--toflag (mutually exclusive with--project-id); the old commands remain as hidden, deprecated aliases.envselection by id or case-insensitive name with loud ambiguity /not-found errors instead of a silent fallback to the active environment;
env getis now visible andcreateis a proper alias ofadd.extractionssubcommands reordered to the shared lifecycle order used bythe other primitives, so every primitive's
--helpreads the same.--helprecategorized by backend role (Primitives · Resources ·Workflows · Organization · Account · Setup), so backend resources no longer
sit in an anonymous "Other" bucket next to the local-only
setup/synctools. A guard test fails if a future top-level command is left
uncategorized.
Bug fix included
cli/cmd/main_test.gonow isolates bothHOMEand%USERPROFILE%in aTestMain. Previously the cmd tests only isolated$HOME, but config resolvesvia
os.UserHomeDir()(=%USERPROFILE%on Windows), so config-writing testscould overwrite a developer's real
~/.retab/config.json.Testing
go build ./...✅go vet ./cmd/✅gofmtclean ✅go test ./...— green except 12 pre-existing Windows-only failures(Unix file-mode/exec-bit/
/tmpassertions); these fail identically on aclean
mainbaseline and are unrelated to this change. The design/parity/helpcontract tests (
api_design_*,sdk_parity,help) all pass.Notes for reviewers
commands outright, while
spec plan-to/apply-toandenv createare keptas hidden aliases. Happy to align on one convention.
.gitattributesenforcing LF, soWindows checkouts (
core.autocrlf=true) tripgofmt -lon every file; andno CI workflow runs
go test/go vet. Both are out of scope here but worth afollow-up.