@labelbox/rl-sdk
v0.0.153
Published
The rl-gym TypeScript SDK, **generated from the backend OpenAPI spec** with [`@hey-api/openapi-ts`](https://heyapi.dev). Almost the entire package is generated — the only hand-written code is the path reader (`src/nesting.ts`) and a thin auth constructor
Maintainers
Keywords
Readme
@labelbox/rl-sdk
The rl-gym TypeScript SDK, generated from the backend OpenAPI spec with
@hey-api/openapi-ts. Almost the entire package is
generated — the only hand-written code is the path reader (src/nesting.ts) and
a thin auth constructor (src/index.ts).
import { createRecursionClient } from '@labelbox/rl-sdk';
const rl = createRecursionClient({ apiKey: process.env.LABELBOX_API_KEY });
const job = await rl.synthesizers.create({
environmentId: 'env_…',
body: { name: 'Variant generator', systemPrompt: '…' },
});Install
Published to public npm as @labelbox/rl-sdk — no registry configuration,
repository access, or install-time credential is needed:
npm install @labelbox/rl-sdkFull setup steps:
apps/recursion/web/public/docs/ts-sdk-getting-started.md. The SDK releases independently
of the CLI: a packages/sdk-ts/** change (e.g. a committed openapi.json update)
cuts an SDK release via the Release / SDK GitHub Action — see yarn dx help release.
Surface
Calls use flat params — path/query values and the request body are all top-level
keys of a single options argument; the request body sits under body.
Instance-based: rl.<namespace>.<method>(...).
The body param would otherwise be named after its DTO (e.g.
createSynthesizerJobBodyDto) — yarn dx sdk:generate renames it to body via a
deterministic post-pass (renameBodyParam in tools/dx/src/commands/sdk.ts),
since hey-api offers no lever for this.
Opt-in, declared at the source. An operation is in the SDK iff its backend
handler carries @SdkRoute(...segments) (apps/recursion/api/src/common/sdk-route.decorator.ts),
which emits an x-sdk-path OpenAPI extension. @SdkRoute('synthesizers', 'create')
→ rl.synthesizers.create(...). There is no heuristic and no per-operation
code here — src/nesting.ts just reads the declared paths and asserts (at
codegen time) that every path is unique and a valid identifier. Endpoints without
@SdkRoute are not generated (that is also how you exclude one).
Scope grows by annotating more handlers — e.g. the synthesizer tag is exposed
as rl.synthesizers (jobs) and rl.synthesizerRuns (runs).
Regenerating
# Regenerate the client + the SDK reference docs from the committed spec snapshot.
yarn dx sdk:generate
# Also re-dump the spec snapshot (packages/sdk-ts/openapi.json) from the backend first.
yarn dx sdk:generate --refresh-specsrc/generated/** and src/reference/*.generated.ts are git-ignored and
regenerated from the committed openapi.json by yarn dx codegen on every
install / CI job / build (wired into build:libs, the setup-node-yarn action,
and postinstall). Never hand-edit them; only openapi.json is committed.
Generation choices (and why)
bundle: true— the fetch runtime is vendored intosrc/generatedso the SDK is self-contained and version-locked to the generator (the standalone@hey-api/client-fetchpackage drifts independently).@hey-api/client-fetchis therefore a devDependency, used only at generation time.output.importFileExtension: '.js'— makes generated relative imports compatible with the repo'smoduleResolution: NodeNext.- No
exactOptionalPropertyTypes: true(tsconfig) — the vendored fetch runtime does not satisfy this flag, so this package leaves it off (defaulting to false) while every other package in the repo opts in explicitly. It is the one strictness relaxation this generated-heavy package makes; hand-written code stays clean. src/generatedexcluded from Biome — generated output is not linted; its determinism is what the freshness check relies on.
Docs
The generated SDK reference shown in the in-app API docs is derived from the
same spec by yarn dx sdk:generate into this package's ./reference export
(SDK_REFERENCE, with its ./schema shape), keyed by operationId so each
operation's doc page renders its TS SDK / CLI / cURL examples.
