Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .agents/skills/contribute-api/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: contribute-api
description: Contribute a new NeMo Fabric public API surface safely, with Rust, CLI, Python, schema, adapter, and documentation parity in mind
description: Contribute a new NVIDIA NeMo Fabric public API surface safely, with Rust, CLI, Python, TypeScript, schema, adapter, and documentation parity in mind
author: NVIDIA Corporation and Affiliates
license: Apache-2.0
---
Expand All @@ -20,8 +20,8 @@ runtime or bindings.
## Default Guidance

- Start from the shared Rust core behavior first
- Decide whether the CLI, PyO3 binding, Python SDK, type stubs, schemas, or
adapter contract must expose the new surface
- Decide whether the CLI, PyO3 binding, Python SDK, type stubs, schemas, or the
Python and TypeScript adapter-contract bindings must expose the new surface
- Keep every affected public surface in parity
- Update docs and examples in the same branch

Expand All @@ -37,4 +37,5 @@ runtime or bindings.
- `validate-change`
- `review-doc-style`
- `docs/python-sdk-contract.md`
- `schemas/SCHEMA.md`
- `justfile`
13 changes: 12 additions & 1 deletion .agents/skills/maintain-packaging/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: maintain-packaging
description: Maintain NeMo Fabric Rust and Python dependencies, package metadata, module paths, native artifacts, lockfiles, license evidence, and release-facing build surfaces
description: Maintain NVIDIA NeMo Fabric Rust, Python, and TypeScript dependencies, package metadata, module paths, native artifacts, lockfiles, license evidence, and release-facing build surfaces
author: NVIDIA Corporation and Affiliates
license: Apache-2.0
---
Expand All @@ -24,6 +24,8 @@ consumed outside the source tree.
- Python package metadata in `python/pyproject.toml`
- Native extension naming and placement under `python/src/nemo_fabric`
- Dependency resolution in `Cargo.lock` and `uv.lock`
- TypeScript adapter-contract metadata and dependency resolution in
`typescript/adapter-contract/package.json` and `package-lock.json`
- Documentation tooling metadata in `docs/package.json` and
`docs/package-lock.json`
- CI workflows, install commands, and example commands
Expand Down Expand Up @@ -59,6 +61,10 @@ commitment.
`uv run --no-project python scripts/licensing/license_diff.py --base-ref origin/main`
after updating manifests and lockfiles, then review added packages and license
changes.
- For `typescript/adapter-contract/package-lock.json`, inspect the resolved
package entries and their `license` fields. The adapter-contract package must
keep an empty production dependency graph; build-only dependencies still
require permissive, recorded license evidence.
- Regenerate the attribution files with the named pre-commit hooks instead of
editing generated output:

Expand All @@ -78,6 +84,8 @@ compatibility decisions using the distribution and linkage context.
- [ ] CI references the same package names as local workflows
- [ ] Public packaging changes are reflected in release-facing docs
- [ ] Workspace, Python, and lockfile versions remain aligned where required
- [ ] The TypeScript adapter-contract package version follows the workspace
release version without changing its independent wire contract version
- [ ] The editable maturin build still produces `nemo_fabric._native`
- [ ] New dependencies are necessary, maintained, and narrower than the viable
alternatives
Expand All @@ -96,6 +104,9 @@ compatibility decisions using the distribution and linkage context.
- `uv.lock`
- `docs/package.json`
- `docs/package-lock.json`
- `typescript/adapter-contract/package.json`
- `typescript/adapter-contract/package-lock.json`
- `.github/workflows/ci_typescript.yml`
- `.github/workflows/ci_python.yml`
- `.github/workflows/ci_rust.yml`
- `.pre-commit-config.yaml`
Expand Down
28 changes: 21 additions & 7 deletions .agents/skills/update-project-version/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: update-project-version
description: Update the NeMo Fabric release version across Cargo, setuptools package metadata, internal Python dependency pins, integration metadata, and lockfiles. Use when bumping, synchronizing, or auditing NeMo Fabric package versions for a release.
description: Update the NVIDIA NeMo Fabric release version across Cargo, Python, and TypeScript package metadata, internal Python dependency pins, integration metadata, and lockfiles. Use when bumping, synchronizing, or auditing NeMo Fabric package versions for a release.
author: NVIDIA Corporation and Affiliates
license: Apache-2.0
---
Expand All @@ -20,7 +20,8 @@ pre-release or build-metadata variants used during packaging.
## Source Of Truth

- `Cargo.toml` `[workspace.package].version` is the source of truth for the Rust
workspace and Python build versioning.
workspace and the release version stamped into Python and TypeScript package
metadata.
- Keep `Cargo.toml` `[workspace.dependencies]` self-references aligned when the
workspace version changes.
- `python/pyproject.toml` is the exception among the Python projects: do not add
Expand All @@ -36,6 +37,8 @@ pre-release or build-metadata variants used during packaging.
- All `nemo-fabric-* == <version>` requirements in the root
`pyproject.toml` optional dependencies.
- Each adapter's `nemo-fabric-adapters-common == <version>` dependency.
- Keep `typescript/adapter-contract/package.json` and the root package entries in
its `package-lock.json` aligned with the Cargo SemVer release version.

For a normal release, use the same `X.Y.Z` string everywhere. For a prerelease
or build-metadata version, use valid Cargo SemVer in `Cargo.toml` and the
Expand All @@ -45,15 +48,17 @@ versions rather than blindly copying incompatible syntax.

## Workflow

1. Read the current version from `Cargo.toml` and decide the exact Cargo and
Python target version strings.
2. Run `just set-version <cargo-version>`. The recipe converts supported Cargo
SemVer prereleases to PEP 440 and updates:
1. Read the current version from `Cargo.toml` and decide the exact Cargo,
Python, and TypeScript target version strings.
2. Run `just set-version <cargo-version>`. The recipe preserves the normalized
SemVer for Cargo and TypeScript, converts it to PEP 440 for Python, and
updates:
- `Cargo.toml` `[workspace.package].version`
- `Cargo.toml` `workspace.dependencies.nemo-fabric-core.version`
- The root setuptools `project.version` and every
`adapters/**/pyproject.toml` `project.version`
- Every internal `nemo-fabric-*` exact-version requirement
- The TypeScript adapter-contract `package.json` and `package-lock.json`
- `Cargo.lock` through Cargo metadata resolution
- The root, runtime, and adapter `uv.lock` files through `just lock-python`
3. Confirm that `python/pyproject.toml` remains dynamic and unchanged.
Expand All @@ -62,14 +67,17 @@ versions rather than blindly copying incompatible syntax.

If editing the helper code, keep these contracts aligned:

- `set_project_version` must call the Cargo and Python project version helpers.
- `set_project_version` must call the Cargo, Python, and TypeScript project
version helpers.
- `set_cargo_workspace_version` must update the workspace version and the
`nemo-fabric-core` workspace dependency, then verify every `nemo-fabric-*` workspace
package through Cargo metadata.
- `set_python_project_versions` must update the root setuptools version, every
adapter `pyproject.toml` discovered recursively under `adapters/`, and all
internal exact-version pins while rejecting a static version in
`python/pyproject.toml`.
- `set_typescript_project_version` must update the package manifest and both
root version entries in the npm lockfile without changing dependency versions.
- The `set-version` recipe must run `just lock-python` after source metadata is
updated.

Expand All @@ -81,11 +89,14 @@ If editing the helper code, keep these contracts aligned:
`rg -n '^version =|nemo-fabric-[a-z-]+ == ' pyproject.toml adapters --glob 'pyproject.toml'`
- Confirm the runtime remains dynamic:
`rg -n 'dynamic = \["version"\]' python/pyproject.toml`
- Inspect the TypeScript package and lockfile root versions:
`rg -n '"version":' typescript/adapter-contract/package{,-lock}.json`
- Run `cargo check --workspace --locked`.
- Run `just build-python` to verify all Python package metadata resolves.
- Run `just test-python` when the integration version or Python packaging
behavior changes materially.
- Run `just wheels` for release-facing validation of every Python wheel.
- Run `just pack-typescript` to verify the stamped TypeScript package metadata.
- Run `git diff --check`.

## Avoid
Expand All @@ -94,6 +105,7 @@ If editing the helper code, keep these contracts aligned:
- Adding a literal version to `python/pyproject.toml`; Maturin owns that version.
- Updating Python package versions without their exact internal dependency pins.
- Forgetting `Cargo.lock`, the root `uv.lock`, or per-project `uv.lock` files.
- Updating the TypeScript package manifest without its npm lockfile root entry.
- Blind repository-wide replacement of version-like strings.

## References
Expand All @@ -106,4 +118,6 @@ If editing the helper code, keep these contracts aligned:
- `python/uv.lock`
- `adapters/**/pyproject.toml`
- `adapters/**/uv.lock`
- `typescript/adapter-contract/package.json`
- `typescript/adapter-contract/package-lock.json`
- `justfile`
20 changes: 17 additions & 3 deletions .agents/skills/validate-change/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,22 @@ surfaces touched by a change.
test pass.
- If Rust code changed, run `cargo fmt --all -- --check` and `just test-rust`.
- If Python code or a Python-facing adapter changed, run `just test-python`.
- If the TypeScript adapter contract or one of its source schemas changed, run
`just test-typescript`.
- If `crates/fabric-core` changed in a way exposed through Python, run both the
Rust and Python suites.
- If the PyO3 bridge or package metadata changed, run `just build-python` and
`cargo check -p fabric-python --locked`.
- If public configuration types changed, confirm the schema snapshot tests in
`just test-rust` pass and review generated schema diffs.
- If an adapter or integration changed, run its focused tests.
- If a manifest or lockfile changed, run
- If a Cargo or Python manifest or lockfile changed, run
`uv run --no-project python scripts/licensing/license_diff.py --base-ref origin/main`,
review the transitive license changes, then run the `attributions-rust` and
`attributions-python` pre-commit hooks.
- If the TypeScript manifest or npm lockfile changed, inspect the complete npm
dependency tree and license fields, confirm the package still has zero
production dependencies, and run its package and audit checks.
- If documentation or examples changed, run `just docs` when practical and
verify documented commands against the current repository.
- If code changes alter APIs, commands, paths, packaging behavior, telemetry
Expand All @@ -55,8 +60,9 @@ surfaces touched by a change.
- **Harbor integration changed**
Run `tests/test_harbor_runner.py`, then `just test-python`.
- **Schema or public contract changed**
Run both language suites and review changes under `schemas/` and generated API
references.
Run the Rust, Python, and TypeScript suites and review changes under
`schemas/`, the checked-in Python adapter-contract representations, generated
TypeScript sources, and generated API references.
- **Documentation-only change**
Use `contribute-docs` and `review-doc-style`. Run `just docs` for docs-site or
generated-reference changes.
Expand All @@ -69,6 +75,7 @@ surfaces touched by a change.
```bash
just test-rust
just test-python
just test-typescript
```

## Common Targeted Commands
Expand All @@ -85,6 +92,11 @@ just build-python
just test-python
uv run --no-sync pytest -k "<pattern>"

# TypeScript adapter contract
just build-typescript
just test-typescript
just pack-typescript

# Documentation
just docs

Expand Down Expand Up @@ -114,5 +126,7 @@ Before review or handoff:
- Build and test recipes: `justfile`
- Python CI: `.github/workflows/ci_python.yml`
- Rust CI: `.github/workflows/ci_rust.yml`
- TypeScript CI: `.github/workflows/ci_typescript.yml`
- Documentation CI: `.github/workflows/fern-docs.yml`
- Public Python contract: `docs/python-sdk-contract.md`
- Public adapter contract: `schemas/SCHEMA.md`
49 changes: 49 additions & 0 deletions .github/workflows/ci_typescript.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

name: TypeScript

on:
pull_request:
push:
branches: [main]

concurrency:
group: ci-typescript-${{ github.ref }}
cancel-in-progress: true

defaults:
run:
shell: bash

jobs:
test:
name: Test (Node ${{ matrix.node-version }})
runs-on: ubuntu-24.04
timeout-minutes: 15
permissions:
contents: read
strategy:
fail-fast: false
matrix:
node-version: ['20.18.3', '24']
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

- name: Set up Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: ${{ matrix.node-version }}
cache: npm
cache-dependency-path: typescript/adapter-contract/package-lock.json

- name: Install just
uses: taiki-e/install-action@c070f87102a1c75b3183910f391c1cb887fe13c8 # v2.77.6
with:
tool: just@1.50.0

- name: Test TypeScript contract package
run: just test-typescript
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repos:
name: copyright header
entry: python3 scripts/lint/check_copyright.py
language: system
files: '\.(rs|py|pyi|toml|yaml|yml|md|mdx|sh)$|\.gitignore$'
files: '\.(rs|py|pyi|toml|yaml|yml|md|mdx|sh|js|mjs|ts|tsx)$|\.gitignore$'
exclude: '(/SKILL\.md|node_modules/|target/|\.venv/|^\.github/pull_request_template\.md)$'

# Python lint — enforce the flake8-bugbear cached-instance-method rule (B019)
Expand Down
7 changes: 6 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,12 @@ These workflow notes keep public documentation, examples, and PR preparation ali
with repository expectations.

- Update user-facing entry points when public behavior, the `nemo-fabric` package (imported as `nemo_fabric`), examples, or supported bindings change: `README.md`, the Fern docs under `docs/` (navigation in `docs/index.yml`, site config in `fern/docs.yml`), and the adapter/integration READMEs (`adapters/*/README.md`, `python/src/nemo_fabric/integrations/*/README.md`, `examples/README.md`).
- Keep the Python/Rust binding contract current when the public API changes: `docs/sdk/python.mdx`, the JSON Schema notes in `schemas/SCHEMA.md`, the generated references under `docs/reference/api/`, and the integration skills under `skills/` (which restate public contracts and must be kept in parity). Regenerate docs with `just docs` after changing the docs site.
- Keep public bindings current when the API changes: `docs/sdk/python.mdx` for
the Python SDK; `adapter-contract/` and `typescript/adapter-contract/` for the
southbound adapter contract; the JSON Schema notes in `schemas/SCHEMA.md`;
the generated references under `docs/reference/api/`; and the integration
skills under `skills/` (which restate public contracts and must be kept in
parity). Regenerate docs with `just docs` after changing the docs site.
- Keep release policy and the end-to-end maintainer workflow in `RELEASING.md`; keep packaging implementation guidance in `.agents/skills/maintain-packaging/SKILL.md`. Do not move release-history policy into user-facing docs or add a duplicate `CHANGELOG.md`.
- Keep the stable public wrapper `scripts/generate_api_docs.sh` at the `scripts/` root in docs and examples. Reference namespaced helper paths under `scripts/docs/` only when documenting internal maintenance work.
- Use branch prefixes for your work: `feat/`, `fix/`, `docs/`, `test/`, or `refactor/`.
Expand Down
33 changes: 23 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ Install these tools before you start:

- **Rust** (stable toolchain) -- install with [rustup](https://rustup.rs/)
- **Python** >= 3.11
- **Node.js** >= 20.18.3 with npm
- **uv** -- follow the [uv installation guide](https://docs.astral.sh/uv/getting-started/installation/)
- **just** >= 1.50.0 -- `cargo install just --locked`

Clone the repository, create a virtual environment, and build the Rust and
Python packages:
Clone the repository, create a virtual environment, and build the Rust,
Python, and TypeScript packages:

```bash
git clone https://github.com/NVIDIA/NeMo-Fabric.git
Expand Down Expand Up @@ -99,17 +100,25 @@ Follow the existing style in the Python SDK, adapters, examples, and tests.
Use type annotations for public APIs and keep native binding declarations in
sync with their Rust implementations.

### TypeScript

Use strict TypeScript for the adapter-contract binding. Preserve the JSON wire
property names, run the checked-in generator instead of editing generated
declarations, and keep production dependencies out of the contract package.

### General

Use the naming conventions appropriate to each language: Rust and Python use
`snake_case` for functions and variables, Rust types use `PascalCase`, and
Python classes use `PascalCase`.
Use the naming conventions appropriate to each language. Rust and Python use
`snake_case` for functions and variables. Rust, Python, and TypeScript types use
`PascalCase`. TypeScript contract properties preserve the wire `snake_case`
names.

## Testing

**Run tests for every language surface affected by your changes.** If a change
touches the Rust core or public schemas, run both the Rust and Python suites
because the Python SDK and adapters depend on the native core contract.
touches the Rust core or public adapter-contract schemas, run the Rust, Python,
and TypeScript suites because both language bindings depend on the generated
wire contract.

Run the affected test targets through the repository `justfile`:

Expand All @@ -120,7 +129,10 @@ just test-rust
# Python SDK, adapters, integrations, and examples
just test-python

# Both suites
# TypeScript adapter contract
just test-typescript

# All supported language surfaces
just test-all
```

Expand All @@ -133,8 +145,9 @@ just no_uv=true test-all
```

When adding functionality, include tests in the corresponding Rust crate or in
the relevant area under `tests/`. Public contract changes must keep the checked-in
JSON Schema snapshots and native Python binding declarations synchronized.
the relevant area under `tests/`. Public contract changes must keep the
checked-in JSON Schema snapshots, Python representations, and generated
TypeScript declarations synchronized.

## Documentation Checklist

Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,16 @@ through adapters. Use the following reference to compare the integrations:

- [Adapter compatibility and guides](adapters/README.md): compare bundled
harness support, runtime ownership, telemetry integration, and package guides.
- [Adapter contract](docs/adapter-contract/README.md): build third-party
adapters against the canonical schemas or the dependency-free Python and
TypeScript contract bindings.

## Roadmap

- **Custom harnesses:** Publish the NeMo Fabric adapter contract so third-party
developers can build integrations that are compatible with NeMo Fabric.
Support integrations maintained by NeMo Fabric and compatible third-party
integrations.
- **Custom harnesses:** Publish the NeMo Fabric adapter contract as canonical
schemas and dependency-free language bindings so third-party developers can
build integrations that are compatible with NeMo Fabric. Support integrations
maintained by NeMo Fabric and compatible third-party integrations.
- **Custom agents:** Support custom agents built on maintained or third-party
harness integrations without requiring an additional, agent-specific adapter.
Preserve the normalized NeMo Fabric lifecycle, results, artifacts, and
Expand Down
Loading
Loading